springboot继承shiro
一般来说,都要一个ShiroConfig类(名字因人而异)来配置下shiro,直接上代码
@Configuration public class ShiroConfig { /** * ShiroFilterFactoryBean 处理拦截资源文件问题。 * 注意:单独一个ShiroFilterFactoryBean配置是或报错的,以为在 * 初始化ShiroFilterFactoryBean的时候需要注入:SecurityManager * * Filter Chain定义说明 1、一个URL可以配置多个Filter,使用逗号分隔 2、当设置多个过滤器时,全部验证通过,才视为通过 * 3、部分过滤器可指定参数,如perms,roles * */ @Bean public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); // 必须设置 SecurityManager shiroFilterFactoryBean.setSecurityManager(securityManager); // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面 shiroFilterFactoryBean.setLoginUrl("/"); // 拦截器. Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>(); // 配置不会被拦截的链接 顺序判断 filterChainDefinitionMap.put("/", "anon"); filterChainDefinitionMap.put("/login.html", "anon"); filterChainDefinitionMap.put("/register.html", "anon"); filterChainDefinitionMap.put("/findPassword.html", "anon"); filterChainDefinitionMap.put("/static/**", "anon"); filterChainDefinitionMap.put("/user/login", "anon"); filterChainDefinitionMap.put("/user/sendEmail", "anon"); filterChainDefinitionMap.put("/user/checkYzm", "anon"); filterChainDefinitionMap.put("/user/register", "anon"); filterChainDefinitionMap.put("/user/sign", "anon"); filterChainDefinitionMap.put("/article/**", "anon"); filterChainDefinitionMap.put("/comment/**", "anon"); filterChainDefinitionMap.put("/image/**", "anon"); filterChainDefinitionMap.put("/userImage/**", "anon"); filterChainDefinitionMap.put("/adminLogin.html", "anon"); filterChainDefinitionMap.put("/toVipPage", "anon"); filterChainDefinitionMap.put("/toDeclarePage", "anon"); filterChainDefinitionMap.put("/favicon.ico", "anon"); filterChainDefinitionMap.put("/alipay/notifyUrl", "anon"); filterChainDefinitionMap.put("/weixinpay/notifyUrl", "anon"); // 配置退出过滤器,其中的具体的退出代码Shiro已经替我们实现了 filterChainDefinitionMap.put("/logout", "logout"); // <!-- 过滤链定义,从上向下顺序执行,一般将 /**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了; // <!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问--> filterChainDefinitionMap.put("/**", "authc"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } @Bean public SecurityManager securityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); // 设置realm. securityManager.setRealm(myRealm()); return securityManager; } /** * 身份认证realm; (这个需要自己写,账号密码校验;权限等) * * @return */ @Bean public MyRealm myRealm() { MyRealm myRealm = new MyRealm(); return myRealm; } /** * Shiro生命周期处理器 * @return */ @Bean public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){ return new LifecycleBeanPostProcessor(); } /** * 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证 * 配置以下两个bean(DefaultAdvisorAutoProxyCreator(可选)和AuthorizationAttributeSourceAdvisor)即可实现此功能 * @return */ @Bean @DependsOn({"lifecycleBeanPostProcessor"}) public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){ DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator(); advisorAutoProxyCreator.setProxyTargetClass(true); return advisorAutoProxyCreator; } @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(){ AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager()); return authorizationAttributeSourceAdvisor; } }
上面只有MyRealm需要自己去定义,然后ShiroFilterFactoryBean 这个方法需要看下路径是怎么拦截的,其他的基本就这样(可能我的比较简单啊)
然后上MyRealm的代码
public class MyRealm extends AuthorizingRealm { @Resource private UserService userService; /** * 授权 */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { String userName=(String) SecurityUtils.getSubject().getPrincipal(); User user=userService.findByUserName(userName); SimpleAuthorizationInfo info=new SimpleAuthorizationInfo(); Set<String> roles=new HashSet<String>(); if("管理员".equals(user.getRoleName())){ roles.add("管理员"); info.addStringPermission("进入管理员主页"); info.addStringPermission("生成所有帖子索引"); info.addStringPermission("分页查询资源帖子信息"); info.addStringPermission("跳转到修改帖子页面"); info.addStringPermission("修改帖子"); info.addStringPermission("图片上传"); info.addStringPermission("删除帖子"); info.addStringPermission("跳转到帖子审核页面"); info.addStringPermission("修改状态"); info.addStringPermission("修改热门状态"); info.addStringPermission("分页查询评论信息"); info.addStringPermission("修改评论状态"); info.addStringPermission("删除评论"); info.addStringPermission("分页查询用户信息"); info.addStringPermission("修改用户VIP状态"); info.addStringPermission("修改用户状态"); info.addStringPermission("重置用户密码"); info.addStringPermission("用户积分充值"); info.addStringPermission("分页查询资源类别信息"); info.addStringPermission("添加或者修改类别信息"); info.addStringPermission("删除类别信息"); info.addStringPermission("根据id查询资源类别实体"); info.addStringPermission("分页查询友情链接"); info.addStringPermission("添加或者修改友情链接"); info.addStringPermission("删除友情链接"); info.addStringPermission("根据id查询友情链接实体"); info.addStringPermission("修改管理员密码"); info.addStringPermission("安全退出"); } info.setRoles(roles); return info; } /** * 登录权限认证 */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { String userName=(String)token.getPrincipal(); User user=userService.findByUserName(userName); if(user!=null){ AuthenticationInfo authcInfo=new SimpleAuthenticationInfo(user.getUserName(),user.getPassword(),"xx"); return authcInfo; }else{ return null; } }
doGetAuthenticationInfo是登录验证,把登录那部分的代码一起上,一起讲,可能比较方便
关键代码:
执行到这一步的时候,先去MyRealm的登录验证的doGetAuthenticationInfo下面的方法,然后先先执行完这个方法,再返回authcInfo,即上面获取的token,如果登录错误,就返回空的,报错
顺便提一下,这里shiro是先判断登录输入的username和数据库查到的username是否存在,如果不存在,直接报错
如果存在再判断通过username查询出来的password和登录时候输入的password是否一致,如果一致,才算登录成功