shiro的流程
1、请求到controller,通过SecurityUtils.getSubject()获取Subject,利用subject.login(usernamePasswordToken),在服务器保存用户的session;
2、如果用户名和密码输入错误,会自动报错。我们需要自己捕获错误。
3、
springBoot+shiro配置
gitee:https://gitee.com/zhengyanzy/project/blob/master/shiro/sprinboot%20shiro.rar
1、配置ShiroConfig
@Configuration public class ShiroConfig { @Bean @ConditionalOnMissingBean public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() { DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator(); defaultAAP.setProxyTargetClass(true); return defaultAAP; } //将自己的验证方式加入容器 @Bean public CustomRealm myShiroRealm() { return new CustomRealm(); } //权限管理,配置主要是Realm的管理认证 @Bean public SecurityManager securityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(myShiroRealm()); return securityManager; } //Filter工厂,设置对应的过滤条件和跳转条件 @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); Map<String, String> map = new HashMap<>(); //登出 map.put("/logout", "logout"); //对所有用户认证 map.put("/**", "authc"); //登录 shiroFilterFactoryBean.setLoginUrl("/login"); //首页 shiroFilterFactoryBean.setSuccessUrl("/index"); //错误页面,认证不通过跳转 shiroFilterFactoryBean.setUnauthorizedUrl("/error"); shiroFilterFactoryBean.setFilterChainDefinitionMap(map); return shiroFilterFactoryBean; } //注入权限管理 @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) { AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); return authorizationAttributeSourceAdvisor; } }
2、配置CustomRealm
public class CustomRealm extends AuthorizingRealm { @Autowired private LoginService loginService; /** * 用户授权 */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { //获取登录用户名 String name = (String) principalCollection.getPrimaryPrincipal(); System.out.println("当前登录的用户名:"+name); //实际情况不应该再去查一边数据库,会从缓存中找出用户对应的权限 User user = loginService.getUserByName(name); //添加角色和权限 SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); for (Role role : user.getRoles()) { //添加角色 simpleAuthorizationInfo.addRole(role.getRoleName()); //添加权限 for (Permissions permissions : role.getPermissions()) { simpleAuthorizationInfo.addStringPermission(permissions.getPermissionsName()); } } return simpleAuthorizationInfo; } /** * 认证用户名和密码 */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { if (StringUtils.isEmpty(authenticationToken.getPrincipal())) { return null; } //前台传入的用户名 String name = authenticationToken.getPrincipal().toString(); //去数据库获取User User user = loginService.getUserByName(name); if (user == null) { //这里返回后会报出对应异常 return null; } else { //这里验证authenticationToken和simpleAuthenticationInfo的信息 SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(name, user.getPassword().toString(), getName()); return simpleAuthenticationInfo; } } }
3、用户登录
@PostMapping("/login") public String login(User user) { if (StringUtils.isEmpty(user.getUserName()) || StringUtils.isEmpty(user.getPassword())) { return "请输入用户名和密码!"; } //用户认证信息 Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken( user.getUserName(), user.getPassword() ); try { //进行验证,这里可以捕获异常,然后返回对应信息 subject.login(usernamePasswordToken); // subject.checkRole("admin"); // subject.checkPermissions("query", "add"); } catch (UnknownAccountException e) { log.error("用户名不存在!", e); return "用户名不存在!"; } catch (AuthenticationException e) { log.error("账号或密码错误!", e); return "账号或密码错误!"; } catch (AuthorizationException e) { log.error("没有权限!", e); return "没有权限"; } return "login success"; }