springboot集成shiro(包括所出现的问题)
时间:2020-04-07 09:02:51
收藏:0
阅读:152
一,自定义realm,继承授权AuthorizingRealm
package com.dkepay.dkpadmin.common.shiro; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.dkepay.dkpadmin.common.config.ApplicationContextRegister; import com.dkepay.dkpadmin.common.entity.sys.SysUserEntity; import com.dkepay.dkpadmin.common.utils.ShiroUtils; import com.dkepay.dkpadmin.dao.SysUserDao; import com.dkepay.dkpadmin.service.SysMenuService; import lombok.extern.slf4j.Slf4j; import org.apache.shiro.authc.*; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import java.util.Set; /** */ @Slf4j public class SysUserRealm extends AuthorizingRealm { /** * 获取授权信息 * @param principals * @return */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { log.info("授权信息开始---》"); Integer uId = ShiroUtils.getUid(); log.info("获取用户uId:[{}]",uId); SysMenuService menuService = ApplicationContextRegister.getBean(SysMenuService.class); Set<String> perms = menuService.listPerms(uId); log.info("获取用户权限perms:[{}]",perms); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); info.setStringPermissions(perms); log.info("授权信息结束---》"); return info; } /** * 获取认证信息 * @param token * @return * @throws AuthenticationException */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { log.info("认证信息开始---》"); // 获取用户账号(也就是手机号) String accountNumber = (String) token.getPrincipal(); log.info("获取到的用户账号accountNumber:[{}]",accountNumber); // 获取密码 String password = new String((char[]) token.getCredentials()); log.info("获取到的密码password:[{}]",password); SysUserDao sysUserDao = ApplicationContextRegister.getBean(SysUserDao.class); // 根据用户账号查询数据库 QueryWrapper<SysUserEntity> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("mobile",accountNumber); // 查询用户信息 SysUserEntity sysUserEntity = sysUserDao.selectOne(queryWrapper); log.info("查询到的用户对象sysUserEntity:[{}]",sysUserEntity); // 账号不存在 if (sysUserEntity == null) { throw new UnknownAccountException("账号或密码不正确"); } // 密码错误 if (!password.equals(sysUserEntity.getPassword())) { throw new IncorrectCredentialsException("账号或密码不正确"); } // 账号锁定 if (sysUserEntity.getStatus() == 0) { throw new LockedAccountException("账号已被锁定,请联系管理员"); } SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(sysUserEntity, password, getName()); log.info("认证信息结束---》"); return info; } }
二,配置shiroConfig(还要给安全管理器指定要连接的realm,代码中有)
package com.dkepay.dkpadmin.common.config; import com.dkepay.dkpadmin.common.shiro.SysUserRealm; import org.apache.shiro.spring.LifecycleBeanPostProcessor; import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; import java.util.LinkedHashMap; /** * @Configuration 声明当前类为配置类,创建对象 * 相当于@Component */ @Configuration public class ShiroConfig { /** * 创建一个 ShiroFilterFactoryBean 创建一个过滤器工厂 * @Bean 所在的方法,如果方法形参中写的对象类型在工厂中恰好有一个对象,会自定装配上 */ @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager){ ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean(); //过滤原则 ,要拦截哪些请求 //配置拦截规则,哪些页面拦截,哪些不拦截,过滤器链 LinkedHashMap<String, String> map = new LinkedHashMap<>(); /** * anon 代表匿名可访问,就是不用登陆就可以访问 * authc 代表登陆后才能访问 * 支持通配符* * 注意:拦截规则 一个一个配置 */ // 拦截接口 // 配置退出过滤器,其中的具体的退出代码Shiro已经替我们实现了 map.put("/logout","logout"); map.put("/sys/**","authc"); // 拦截页面 map.put("/**","anon"); map.put("/home/*","authc"); // 被拦截返回登录页面 // factoryBean.setLoginUrl("/home/login"); // 未授权界面; // factoryBean.setUnauthorizedUrl("/500x.html"); factoryBean.setFilterChainDefinitionMap(map); //需要安全管理器 factoryBean.setSecurityManager(securityManager); return factoryBean; } /** * 创建一个安全管理器 */ @Bean public DefaultWebSecurityManager securityManager(SysUserRealm sysUserRealm){ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); //给安全管理器赋值一个realm,声明使用哪个realm securityManager.setRealm(sysUserRealm); return securityManager; } /** *创建realm */ @Bean public SysUserRealm sysUserRealm(){ return new SysUserRealm(); } /** * Shiro生命周期处理器 */ @Bean(name = "lifecycleBeanPostProcessor") public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() { return new LifecycleBeanPostProcessor(); } /** * 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证 */ @Bean @DependsOn("lifecycleBeanPostProcessor") public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() { DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator(); creator.setProxyTargetClass(true); return creator; } /** * 开启shiro aop注解支持 * 使用代理方式;所以需要开启代码支持;否则@RequiresRoles等注解无法生效 * @param securityManager * @return */ @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager){ AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); return authorizationAttributeSourceAdvisor; } }
三,在controller层对应的方法上加注解(@RequiresPermissions("sys:menus"))
认证成功,则会根据注解上的权限字符串进入到授权的方法里(在自定义的realm里),根据认证通过的主体也就是Subject里面的用户id去数据库查询权限字符串,有就封装到info返回.没有就报Subject does not have permission [sys:menus]异常,也就是该用户没有该权限.
四,@RequiresPermissions注解无效
有可能是在shiroConfig中少加了两个配置
/** * Shiro生命周期处理器 */ @Bean(name = "lifecycleBeanPostProcessor") public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() { return new LifecycleBeanPostProcessor(); } /** * 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证 */ @Bean @DependsOn("lifecycleBeanPostProcessor") public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() { DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator(); creator.setProxyTargetClass(true); return creator; }
原文:https://www.cnblogs.com/y7023/p/12650676.html
评论(0)