SpringBoot整合Shiro实现用户认证
添加依赖 org.apache.shiro shiro-spring 1.4.0
前端测试代码
controller(控制层) @RequestMapping("toLogin") public String toLogin(String userName,String password,Model model){ // 使用shiro 编写登录逻辑 // 1。获取subject Subject subject = SecurityUtils.getSubject(); //2。将参数封装成token UsernamePasswordToken token = new UsernamePasswordToken(userName,password); //3。执行登录 try{ subject.login(token); return "logins"; }catch (UnknownAccountException e){ model.addAttribute("message","用户不存在"); return "login"; }catch (IncorrectCredentialsException e){ model.addAttribute("message","密码错误"); return "login"; } }
ShiroConfig(配置类) @Configuration public class ShiroConfig { /* * 创建 ShiroFilterFactoryBean 对象 * */ @Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(){ // 创建过滤器 ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); // 设置安全管理器 shiroFilterFactoryBean.setSecurityManager(getDefaultWebSecurityManager()); //添加shiro 内置过滤器 /* * shiro 内置过滤器 ,可以实现权限相关的拦截器 * * 常用的过滤器() * anon:无需认证可以访问 * authc:必须认证才可以访问 * user: 如果使用rememberme的功能可以访问 * perms:该资源必须得到资源权限才可以访问 * role:该资源必须得到角色权限才可以访问 * */ Map filterMap = new LinkedHashMap<>(); // 放过的路径 filterMap.put("/shiroController/index","anon"); filterMap.put("/loginController/toLogin","anon");//key:访问路径 value:过滤级别 //拦截所有 filterMap.put("/**","authc"); //强行跳转的页面 shiroFilterFactoryBean.setLoginUrl("/loginController/login"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap); return shiroFilterFactoryBean; } /* * 创建 DefaultWebSecurityManager 用来管理用户主体的subject * */ @Bean public DefaultWebSecurityManager getDefaultWebSecurityManager(){ DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager(); defaultWebSecurityManager.setRealm(getUserRealm()); return defaultWebSecurityManager; } // 使用哈希算法+盐值加密 需要给盐 和 次数 @Bean public UserRealm getUserRealm(){ UserRealm userRealm = new UserRealm(); userRealm.setCredentialsMatcher(getHashedCredentialsMatcher()); return userRealm; } /* * 设置哈希算法 * */ @Bean public HashedCredentialsMatcher getHashedCredentialsMatcher() { //创建hashedCredentialsMatcher 对象 HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); //指定加密方式 MD4 MD5 SHA-1 SHA-256 SHA-384 SHA-512 hashedCredentialsMatcher.setHashAlgorithmName("md5"); //设置加密次数 必须和UserRealm hashedCredentialsMatcher.setHashIterations(1); //设置加密的编码 true:加密使用的是HEX编码 false:base6编码 hashedCredentialsMatcher.setStoredCredentialsHexEncoded(true); return hashedCredentialsMatcher; } }
UserRealm(认证) public class UserRealm extends AuthorizingRealm { @Autowired private UserServiceI userService; @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { /* * 执行授权逻辑 * */ System.out.println("》》》》》执行授权逻辑《《《《《《《"); return null; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { /* * 执行认证逻辑 * */ System.out.println("》》》》》》》》》执行认证逻辑《《《《《《《《《《"); UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken; //调用数据库进行验证 TbUser user = userService.findUserInfoByUserName(token.getUsername()); // 编写登录认证逻辑 if (!token.getUsername().equals(user.getTbUserName())){ return null; } //判断密码 //假设密码正确,也就是登陆成功后的用户密码,好比将他放入到session中 // 数据库查询出来的密码,shiro自动校验 //加的盐 ByteSource.Util.bytes(user.getTbSalt()) //假设密码正确,也就是登陆成功后的用户名 //盐相当于密钥 //shiro 加密方式 盐+次数 进行哈希加密 // return new SimpleAuthenticationInfo(user,user.getTbUserPwd(), ByteSource.Util.bytes(user.getTbSalt()),user.getTbUserName()); } //8fd2fae312c4e621271ea80088cac3a3 public static void main(String[] args) { String s = ShiroUtils.encryptPassword("MD5", "1234", "c440e502", 1); System.out.println(s); } }
ShiroUtils (随机生成 salt) public class ShiroUtils { /** * 随机生成 salt 需要指定 它的字符串的长度 * * @param len 字符串的长度 * @return salt */ public static String generateSalt(int len) { //一个Byte占两个字节 int byteLen = len >> 1; SecureRandomNumberGenerator secureRandom = new SecureRandomNumberGenerator(); return secureRandom.nextBytes(byteLen).toHex(); } /** * 获取加密后的密码,使用默认hash迭代的次数 1 次 * * @param hashAlgorithm hash算法名称 MD2、MD5、SHA-1、SHA-256、SHA-384、SHA-512、etc。 * @param password 需要加密的密码 * @param salt 盐 * @return 加密后的密码 */ public static String encryptPassword(String hashAlgorithm, String password, String salt) { return encryptPassword(hashAlgorithm, password, salt, 1); } /** * 获取加密后的密码,需要指定 hash迭代的次数 * * @param hashAlgorithm hash算法名称 MD2、MD5、SHA-1、SHA-256、SHA-384、SHA-512、etc。 * @param password 需要加密的密码 * @param salt 盐 * @param hashIterations hash迭代的次数 * @return 加密后的密码 */ public static String encryptPassword(String hashAlgorithm, String password, String salt, int hashIterations) { SimpleHash hash = new SimpleHash(hashAlgorithm, password, salt, hashIterations); return hash.toString(); } public static void main(String[] args) { String s = ShiroUtils.generateSalt(8); System.out.println(s); } }