SpringBoot之集成Shiro中出现的一个问题logout没有作用(实际上时authcBasic导致的问题)

1.声明

当前的内容用于本人学习和使用之用,关于本人在一次偶然的机会发现的一个bug,一个关于shiro的bug(SpringBoot中集成Shiro的时候调用logout出现的bug)

2.pom文件配置

<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>2.2.5.RELEASE</version>
	<relativePath /> <!-- lookup parent from repository -->
</parent>
<!--  shiro的配置 -->
<dependency>
	<groupId>org.apache.shiro</groupId>
	<artifactId>shiro-core</artifactId>
	<version>1.4.1</version>
</dependency>
<!-- 使用注解版的权限管理需要开启aop -->
<dependency>
	<groupId>org.apache.shiro</groupId>
	<artifactId>shiro-aspectj</artifactId>
	<version>1.4.1</version>
</dependency>
<dependency>
	<groupId>org.apache.shiro</groupId>
	<artifactId>shiro-spring</artifactId>
	<version>1.4.1</version>
</dependency>
<!-- 配置shiro的会话缓存 -->
<dependency>
	<groupId>org.apache.shiro</groupId>
	<artifactId>shiro-ehcache</artifactId>
	<version>1.4.1</version>
</dependency>
		

springboot2.2.5.RELEASE和shiro1.4.1集成

3.ShiroConfig文件和其他的配置文件

@Configuration
@ConditionalOnClass({ SecurityManager.class, ShiroFilterFactoryBean.class, AuthorizationAttributeSourceAdvisor.class })
public class ShiroConfig {

	// 启动基于ini配置的方式认证,这里可以使用jdbc方式进行身份的验证
	public Realm realm() {

		/*
		 * JdbcRealm jdbcRealm = new JdbcRealm();
		 * jdbcRealm.setPermissionsLookupEnabled(true);
		 * jdbcRealm.setDataSource(dataSource);
		 */
		// 开启默认自动查找权限

		// 或者使用自定义的Realm方式
		IniRealm iniRealm = new IniRealm("classpath:shiro.ini");
		/*
		 * iniRealm.setAuthenticationCachingEnabled(true);
		 * iniRealm.setAuthorizationCachingEnabled(true);
		 */
		return iniRealm;
	}

	// 创建校验管理器
	@Bean
	public DefaultWebSecurityManager securityManager() {
		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
		securityManager.setRealm(realm());
		securityManager.setSessionManager(defaultWebSessionManager());
		return securityManager;
	}

	// 创建Shiro过滤器

	@Bean
	public ShiroFilterFactoryBean shiroFilterFactoryBean(@Autowired DefaultWebSecurityManager securityManager) {
		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
		shiroFilterFactoryBean.setSecurityManager(securityManager);

		Map<String, String> map = new HashMap<String, String>(); // 登出 //
		//map.put("/logout", "logout"); // 默认的退出登录方式,使用spring方式实现
		map.put("/**", "authcBasic"); // 对所有用户认证 // 登录页面使用get方式
		shiroFilterFactoryBean.setLoginUrl("/login"); // 首页get方式
		shiroFilterFactoryBean.setSuccessUrl("/index"); // 错误页面,认证不通过跳转
		shiroFilterFactoryBean.setUnauthorizedUrl("/error");
		shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
		return shiroFilterFactoryBean;
	}

	@Bean
	public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(
			@Autowired DefaultWebSecurityManager securityManager) {
		AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
		authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
		return authorizationAttributeSourceAdvisor;
	}
}

shiro.ini配置文件

[main]
authcBasic.applicationName=please login
sessionManager=org.apache.shiro.web.session.mgt.DefaultWebSessionManager
sessionDAO=org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO
sessionDAO.activeSessionsCacheName=shiro-activeSessionCache
sessionManager.sessionDAO= s e s s i o n D A O c a c h e M a n a g e r = o r g . a p a c h e . s h i r o . c a c h e . e h c a c h e . E h C a c h e M a n a g e r c a c h e M a n a g e r . c a c h e M a n a g e r C o n f i g F i l e = c l a s s p a t h : s h i r o − e h c a c h e . x m l s e c u r i t y M a n a g e r . c a c h e M a n a g e r = sessionDAO cacheManager=org.apache.shiro.cache.ehcache.EhCacheManager cacheManager.cacheManagerConfigFile=classpath:shiro-ehcache.xml securityManager.cacheManager= sessionDAOcacheManager=org.apache.shiro.cache.ehcache.EhCacheManagercacheManager.cacheManagerConfigFile=classpath:shiroehcache.xmlsecurityManager.cacheManager=cacheManager
[users]
admin=admin,admin
user=user,user
[roles]
admin=insert,update,delete,select
user=select
[urls]
#/login=anon
#/logout=logout
#/unauthorized=anon
#/static/**=anon
#/authenticated=authc
#直接使用authcBasic,就是会弹出认证的输入框
#/role=authcBasic,roles[admin]
#/permission=authc,perms[“user:create”]

shiro-ehcache.xml

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
         updateCheck="false">
<cache name="shiro-activeSessionCache"
		maxEntriesLocalHeap="10000"
		overflowToDisk="false"
		eternal="false"
		diskPersistent="false"
		timeToLiveSeconds="0"
		timeToIdleSeconds="0"
		statistics="true"/>
</ehcache>

4.创建访问的ShiroController

@Controller
public class ShiroController {
	@RequiresRoles(value = { "admin" }) 
	@RequestMapping("/getShiroSubject")
	@org.springframework.web.bind.annotation.ResponseBody
	public ResponseBody getShiroSubject() {
		Subject subject = SecurityUtils.getSubject();
		Object loginUser = subject.getPrincipal();
		// 获取当前登录的用户,如何获取会话中的权限
		return ResponseBodyBuilder.instance().ok(loginUser);
	}

	@RequestMapping("/getDatas")
	@org.springframework.web.bind.annotation.ResponseBody
	public ResponseBody getDatas() {
		// 获取当前登录的用户,如何获取会话中的权限
		return ResponseBodyBuilder.instance().ok("成功获取数据");
	}
	// 退出shiro控制

	@RequestMapping("/logout")
	public String logout() {
		Subject subject = SecurityUtils.getSubject(); 
		subject.logout();
		return "redirect:login";
	}

}

5.重现当前的问题logout问题

1.访问logout

在这里插入图片描述
2.由于上面logout是成功的(但是这个地方却可以访问)
在这里插入图片描述
在这里插入图片描述
连带有注解的@RequiresRoles(value = { "admin" }) 都成功了,这是什么鬼?

一个非常诡异的问题产生了,本人通过debug发现确实调用了方法,也没有报错,但是就是shiro都是允许访问的(这是一个bug)

再次访问logout发现还是可以访问
在这里插入图片描述

6.清空浏览器缓存然后再访问

在这里插入图片描述
需要输入密码和用户名

再次登录和退出,以及再次访问又发现可以访问了
在这里插入图片描述

通过不停的调试和排除其他东西,查看原生的servlet中logout是可以执行的(基于ShiroFilter方式是可以实现的)

最后本人无法解决这个问题,所以本人认为这应该就是一个bug

7.解决方案

通过本人的不屑努力,终于发现当前出现问题的地方,在于authcBasic原因是Basic验证时基于HTTP的和SHIRO无关!

参考:解决方案

8.修改当前的shiro.ini配置认证方式为authc

[main]
authcBasic.applicationName=please login
authc.loginUrl=/login
sessionManager=org.apache.shiro.web.session.mgt.DefaultWebSessionManager
sessionDAO=org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO
sessionDAO.activeSessionsCacheName=shiro-activeSessionCache
sessionManager.sessionDAO= s e s s i o n D A O c a c h e M a n a g e r = o r g . a p a c h e . s h i r o . c a c h e . e h c a c h e . E h C a c h e M a n a g e r c a c h e M a n a g e r . c a c h e M a n a g e r C o n f i g F i l e = c l a s s p a t h : s h i r o − e h c a c h e . x m l s e c u r i t y M a n a g e r . c a c h e M a n a g e r = sessionDAO cacheManager=org.apache.shiro.cache.ehcache.EhCacheManager cacheManager.cacheManagerConfigFile=classpath:shiro-ehcache.xml securityManager.cacheManager= sessionDAOcacheManager=org.apache.shiro.cache.ehcache.EhCacheManagercacheManager.cacheManagerConfigFile=classpath:shiroehcache.xmlsecurityManager.cacheManager=cacheManager
sessionManager.sessionIdCookie.path=/
[users]
admin=admin,admin
user=user,user
[roles]
admin=insert,update,delete,select
user=select
[urls]
#/login=anon

修改ShiroConfig文件中的ShiroFilterFactoryBean

@Bean
	public ShiroFilterFactoryBean shiroFilterFactoryBean() {
		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
		shiroFilterFactoryBean.setSecurityManager(securityManager());

		Map<String, String> map = new HashMap<String, String>(); // 登出 //
		//map.put("/logout", "logout"); // 默认的退出登录方式,使用spring方式实现
		map.put("/**", "authc"); // 对所有用户认证 // 登录页面使用get方式
		//map.put("/**", "authcBasic");
		// 注意这里的authcBasic,该验证是BASIC认证都是需要关闭浏览器才清除保存的用户认证信息,跟是否使用shiro无关!
		shiroFilterFactoryBean.setLoginUrl("/login"); // 首页get方式authc.loginUrl = /login
		shiroFilterFactoryBean.setSuccessUrl("/index"); // 错误页面,认证不通过跳转
		shiroFilterFactoryBean.setUnauthorizedUrl("/error");
		shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
		return shiroFilterFactoryBean;
	}

9.创建登录login.html和对应的@RequestMapping

再当前的resources中创建一个文件为login.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<form action="/login" method="post">
		<input type="text" name="username"/><br/>
		<input type="password" name="password"/><br/>
		<input type="submit" value="登录"/>
	</form>
</body>
</html>

对应的@RequestMapping

@RequestMapping(value = "/login", method = RequestMethod.GET)
	public String login() {
		return "login.html";
	}

	@RequestMapping(value = "/login", method = RequestMethod.POST)
	@org.springframework.web.bind.annotation.ResponseBody
	ResponseBody login(String username, String password) {
		Subject subject = SecurityUtils.getSubject();
		subject.login(new UsernamePasswordToken(username, password));
		return ResponseBodyBuilder.instance().ok("登录成功!");

	}

10.测试

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

11.总结

1.在springboot中配置Shiro的时候,一定要注意认证方式,不同的认证方式会产生不同的效果(这里的authcBasic就是一个只和Http有关的认证方式)

2.一般在web环境中只需要使用authc认证即可小心authcBasic(虽然比较简单,但是在前后端分离的时候容易出现问题)

2.当前内容终于解决了

以上纯属个人见解,如有问题请联系本人!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值