Spring boot 整合shiro 实现登陆验证
2017-12-08 15:55
981 查看
一、pom中引入shiro的依赖(省去多余代码)
三个依赖组件,三种用途,已在注释中标注清楚。
二、shiro 配置 ShiroConfiguration,取代以往的 xml 文件,这里使用java 配置。
1、配置过滤器 shiroFilter
2、配置安全管理器 SecurityManager
三、自定义安全领域 SecurityRealm ,继承shiro的抽象类 AuthorizingRealm,重写认证和授权两个方法。本节主要内容是登陆验证,我们只详细实现认证环节。
四、控制器Controller
五、前端页面,任意写一个登陆表单即可验证我这里使用 thymeleaf
六、封装接收请求参数的UserVo 实体类。
github源码:Clone with HTTPS:https://github.com/libinbin8130/personal-websites.git
说明:本章节内容所在项目路径(pw-platform/pf-front/pf-web),由于是多模块项目,pf-web的构建依赖于跟目录pf-front的pom。
<properties> <shiro-version>1.2.5</shiro-version> <extras-shiro-version>1.2.1</extras-shiro-version> </properties> <dependencies> <!-- shiro spring --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>${shiro-version}</version> </dependency> <!-- shiro ehcache (shiro缓存)--> <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-ehcache --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-ehcache</artifactId> <version>${shiro-version}</version> </dependency> <!-- shiro thymeleaf--> <dependency> <groupId>com.github.theborakompanioni</groupId> <artifactId>thymeleaf-extras-shiro</artifactId> <version>${extras-shiro-version}</version> </dependency> </dependencies>
三个依赖组件,三种用途,已在注释中标注清楚。
二、shiro 配置 ShiroConfiguration,取代以往的 xml 文件,这里使用java 配置。
@Configuration public class ShiroConfiguration { //... }
1、配置过滤器 shiroFilter
@Bean(name="shiroFilter") public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager){ ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); shiroFilterFactoryBean.setLoginUrl("/login");//登录连接 shiroFilterFactoryBean.setSuccessUrl("/index");//登录成功后跳转的连接 shiroFilterFactoryBean.setUnauthorizedUrl("/pages/403"); //未授权跳转页面 //定义shiro过滤链 Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>(); //配置退出 filterChainDefinitionMap.put("/logout", "logout"); //配置退出 // <!-- 过滤链定义,从上向下顺序执行,/**放在最下面,过滤链的最后一关,表示除去以上各环节,剩余url的都需要验证 --> // <!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问--> filterChainDefinitionMap.put("/js/**","anon"); filterChainDefinitionMap.put("/css/**","anon"); filterChainDefinitionMap.put("/register","anon"); filterChainDefinitionMap.put("/login", "anon"); filterChainDefinitionMap.put("/**", "authc"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; }
2、配置安全管理器 SecurityManager
@Bean public SecurityManager securityManager(){ //使用默认的安全管理器 DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(securityRealm()); //加入自定义的安全领域 return securityManager; } @Bean public SecurityRealm securityRealm(){ SecurityRealm securityRealm = new SecurityRealm(); securityRealm.setCredentialsMatcher(hashedCredentialsMatcher());//凭证匹配器 securityRealm.setCachingEnabled(false);//不使用缓存 return securityRealm; } @Bean public HashedCredentialsMatcher hashedCredentialsMatcher(){ HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); hashedCredentialsMatcher.setHashAlgorithmName("md5");//使用MD5散列算法 hashedCredentialsMatcher.setHashIterations(1);//散列次数,这里等于1次MD5 hashedCredentialsMatcher.setStoredCredentialsHexEncoded(true); //散列后密码为16进制,要与生成密码时一致。false 表示Base64编码 return hashedCredentialsMatcher; }
三、自定义安全领域 SecurityRealm ,继承shiro的抽象类 AuthorizingRealm,重写认证和授权两个方法。本节主要内容是登陆验证,我们只详细实现认证环节。
public class SecurityRealm extends AuthorizingRealm { /** * 授权 * @param principalCollection * @return */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { String currentUserName = (String)principalCollection.getPrimaryPrincipal(); List<String> roles = new ArrayList<String>(); //角色 List<String> prems = new ArrayList<String>(); //权限 roles.add("baidu"); roles.add("google"); SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); authorizationInfo.addRoles(roles); authorizationInfo.addStringPermissions(prems); return authorizationInfo; } /** * 认证,验证当前登录的Subject * LoginController.login 方法中调用 * @param authenticationToken * @return * @throws AuthenticationException */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { SecurityUtils.getSubject().getSession().getId(),AuthenticationInfo.class); String userName = (String)authenticationToken.getPrincipal(); //为了测试通过,这里暂时写死, user: admin password: 123456 // UserVo user = loginClient.selectUserByName(userName); UserVo user = new UserVo(); user.setName(userName); user.setPassword(new Md5Hash("123456").toHex()); //与SecurityManager加密方式一致,使用一次散列,并转为16进制,验证方能通过。 if(user == null){ throw new UnknownAccountException();//没找到帐号 } //交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配 SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo( "admin", //用户名 user.getPassword(), //密码 getName() //realm name ); return authenticationInfo; } }
四、控制器Controller
@PostMapping("/login") public String login(Model model, @Valid UserVo userVo, BindingResult bindingResult, RedirectAttributes redirectAttributes){ if(bindingResult.hasErrors()){ model.addAttribute("error",bindingResult.getFieldError().getDefaultMessage()); return "login"; } String userName = userVo.getName(); UsernamePasswordToken token = new UsernamePasswordToken(userVo.getName(), userVo.getPassword()); Subject currentUser = SecurityUtils.getSubject(); try { currentUser.login(token); }catch (IncorrectCredentialsException ice){ logger.info("对用户【" + userName +"】进行登录验证,验证未通过,错误的凭证!"); redirectAttributes.addFlashAttribute("error","用户名或密码不正确!"); }catch(UnknownAccountException uae){ logger.info("对用户【" + userName +"】进行登录验证,验证未通过,未知账户!"); redirectAttributes.addFlashAttribute("error","未知账户!"); }catch(LockedAccountException lae){ logger.info("对用户【" + userName +"】进行登录验证,验证未通过,账户锁定!"); redirectAttributes.addFlashAttribute("error","账户已锁定!"); }catch(ExcessiveAttemptsException eae){ logger.info("对用户【" + userName +"】进行登录验证,验证未通过,错误次数太多!"); redirectAttributes.addFlashAttribute("error","用户名或密码错误次数太多!"); }catch(AuthenticationException ae){ logger.info("对用户【" + userName +"】进行登录验证,验证未通过,堆栈轨迹如下:!"); ae.printStackTrace(); redirectAttributes.addFlashAttribute("error","用户名或密码不正确!"); } if(currentUser.isAuthenticated()){ model.addAttribute("name",userName); return "index"; }else{ token.clear(); return "redirect:/login"; } }
五、前端页面,任意写一个登陆表单即可验证我这里使用 thymeleaf
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" /> <title>登录</title> <style> body{ margin-left:auto; margin-right:auto; margin-TOP:100PX; width:20em; } </style> </head> <body> <form th:action="@{/login}" method="post"> <div> <!--/*@thymesVar id="error" type=""*/--> <span id="basic-addon0"> </span> <span style="font-size: 12px;color: red" th:text="${error}" aria-describedby="basic-addon0"></span> <br /> </div> <div> <span id="basic-addon1">@</span> <input id="user_name" name="name" type="text" placeholder="用户名" aria-describedby="basic-addon1" /> </div> <br /> <div> <span id="basic-addon2">@</span> <input id="password" name="password" type="password" placeholder="密码" aria-describedby="basic-addon2" /> </div> <br /> <button type="submit" style="width:190px;">登 录</button> </form> </body> </html>
六、封装接收请求参数的UserVo 实体类。
public class UserVo { @NotEmpty(message="用户名不能为空!") private String name; @Size(min=6,max=10,message = "密码长度必须6到10位") private String password; //...省去getter setter 方法 }
github源码:Clone with HTTPS:https://github.com/libinbin8130/personal-websites.git
说明:本章节内容所在项目路径(pw-platform/pf-front/pf-web),由于是多模块项目,pf-web的构建依赖于跟目录pf-front的pom。
相关文章推荐
- spring boot整合CAS Client实现单点登陆验证的示例
- spring boot mybatis 整合shiro简单实现登陆权限管理
- Spring和Hibernate和Struts整合(二)实现登陆验证
- SpringBoot/SpringMVC整合Shiro(一):实现登录与注册(MD5加盐加密)
- [置顶] 【一】Springboot+Shiro+Mybatis+Thymeleaf实现权限控制和gif验证
- Spring3整合Struts2+Hibernate 实现注册、数据库验证登陆
- spring boot配置shiro安全框架及用户登录权限验证实现
- SpringBoot整合Shiro实现登录认证的方法
- spring boot整合redis实现shiro的分布式session共享
- SpringBoot整合mybatis、shiro、redis实现基于数据库的细粒度动态权限管理系统实例
- SpringBoot整合mybatis、shiro、redis实现基于数据库的细粒度动态权限管理系统实例
- spring boot整合Shiro实现单点登录的示例代码
- SpringBoot整合mybatis、shiro、redis实现基于数据库的细粒度动态权限管理系统实例
- spring boot整合redis,实现shiro的CacheManager
- SpringBoot + thymeleaf 实现简单的登陆验证
- SpringBoot整合mybatis、shiro、redis实现基于数据库的细粒度动态权限管理系统实例(转)
- spring boot整合redis实现shiro的分布式session共享的方法
- Shiro整合Spring实现登录验证和授权之入门
- spring boot整合Shiro实现单点登录
- SpringBoot整合mybatis、shiro、redis实现基于数据库的细粒度动态权限管理系统实例