shrio中hashedCredentialsMatcher密码匹配示例详解
类图如下:
文章图片
SimpleCredentialsMatcher是明文匹配,也是shrio框架默认的比对方式,网上的例子多是此方式。实际项目中,数据库中的密码一般是密文,此时密码的匹配需使用HashedCredentialsMatcher完成。
处理过程
在controller中通过Subject的login(token)将接收过来用户账号和密码(明文)交给shrio框架,示例代码如下
文章图片
其次通过HashedCredentialsMatcher告诉shrio使用加密方式;
文章图片
最后通过AuthorizingRealm,将数据库中获取的密码,告诉shrio框架,shrio处理完成后返回处理结果。
文章图片
示例代码
数据库创建表user,结构如下:
CREATE TABLE `user` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`name` varchar(50) DEFAULT NULL,`psw` varchar(200) DEFAULT NULL,`user_right` varchar(300) DEFAULT NULL,`create_time` date DEFAULT NULL,`salt` varchar(100) DEFAULT NULL,PRIMARY KEY (`id`))
在dao完成根据登录名获取实体对象和增加用户两个方法,略过。service代码如下,保存代码时,密码使用sha256加密,盐随机获取20位随机数
@Service("UserService")public class UserServiceImpl extends ServiceImplimplements UserService {@Overridepublic UserEntity getUserByname(String loginName) {return baseMapper.queryByUserName(loginName); }@Overridepublic boolean save(UserEntity user) {user.setCreateTime(new Date()); String salt = RandomStringUtils.randomAlphanumeric(20); user.setPsw(new Sha256Hash(user.getPsw(), salt).toHex()); //sha256加密user.setSalt(salt); try {baseMapper.insert(user); return true; } catch (Exception e) {return false; }}}
controller代码如下
@RestControllerpublic class UserController {@Autowiredprivate UserService userService; @PostMapping("/login")public Map login(@RequestParam Map params) {String username=params.get("username").toString(); String password=params.get("password").toString(); String result = "已登录"; Subject currentUser = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken(username, password); if (!currentUser.isAuthenticated()) {try {currentUser.login(token); // 会触发com.shiro.config.MyShiroRealm的doGetAuthenticationInfo方法result = "登录成功"; } catch (UnknownAccountException e) {result = "用户名错误"; } catch (IncorrectCredentialsException e) {e.printStackTrace(); result = "密码错误"; }}return R.ok(result); }@GetMapping("/logout")public void logout() {Subject currentUser = SecurityUtils.getSubject(); UserEntity user = (UserEntity)currentUser.getPrincipal(); System.out.println(user.getName()); currentUser.logout(); }@RequestMapping("/user/add")public String add(@RequestBody UserEntity user) {userService.save(user); System.out.println("新增用户"); return "hello"; }}
使用ShiroConfig 代替xml配置文件方式
@Configurationpublic class ShiroConfig {@Beanpublic ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); //设置自定义的securityManagershiroFilterFactoryBean.setSecurityManager(securityManager); //设置默认登录的url,身份认证失败会访问该URLshiroFilterFactoryBean.setLoginUrl("/login"); //设置成功,会访问该urlshiroFilterFactoryBean.setSuccessUrl("/success"); //设置未授权界面,权限认证失败会访问该urlshiroFilterFactoryBean.setUnauthorizedUrl("/notRole"); //进行拦截器配置Map filterChainDefinitionMap = new LinkedHashMap<>(); // filterChainDefinitionMap.put("/webjars/**", "anon"); filterChainDefinitionMap.put("/login", "anon"); filterChainDefinitionMap.put("/", "anon"); filterChainDefinitionMap.put("/front/**", "anon"); filterChainDefinitionMap.put("/user/add", "perms[add]"); filterChainDefinitionMap.put("/admin/**", "authc"); filterChainDefinitionMap.put("/user/**", "authc"); //主要这行代码必须放在所有权限设置的最后,不然会导致所有 url 都被拦截 剩余的都需要认证filterChainDefinitionMap.put("/**", "authc"); //配置logout过滤器filterChainDefinitionMap.put("/logout","logout"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; }@Beanpublic SecurityManager securityManager() {DefaultWebSecurityManager defaultSecurityManager = new DefaultWebSecurityManager(); defaultSecurityManager.setRealm(customRealm()); return defaultSecurityManager; }@Beanpublic CustomRealm customRealm() {CustomRealm customRealm = new CustomRealm(); //SimpleCredentialsMatcher明文匹配,hashedCredentialsMatcher加盐匹配customRealm.setCredentialsMatcher(hashedCredentialsMatcher()); return customRealm; }@Beanpublic HashedCredentialsMatcher hashedCredentialsMatcher() {HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(); hashedCredentialsMatcher.setHashAlgorithmName("SHA-256"); hashedCredentialsMatcher.setHashIterations(1); return hashedCredentialsMatcher; }}
Realm中代码如下:
public class CustomRealm extends AuthorizingRealm {@Autowiredprivate UserService userService; @Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {//授权部分代码略return null; }@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {String loginName = (String) authenticationToken.getPrincipal(); UserEntity user= userService.getUserByname(loginName); if (user == null) {// 没找到帐号 throw new UnknownAccountException(); }// 交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配SimpleAuthenticationInfo authenticationInfo =new SimpleAuthenticationInfo(user, user.getPsw(), ByteSource.Util.bytes(user.getSalt()),getName()); return authenticationInfo; }
测试,使用张三登录
文章图片
文章图片
【shrio中hashedCredentialsMatcher密码匹配示例详解】以上就是shrio中hashedCredentialsMatcher密码匹配示例详解的详细内容,更多关于shrio中hashedCredentialsMatcher密码匹配的资料请关注脚本之家其它相关文章!
推荐阅读
- 热闹中的孤独
- Shell-Bash变量与运算符
- JS中的各种宽高度定义及其应用
- 2021-02-17|2021-02-17 小儿按摩膻中穴-舒缓咳嗽
- 深入理解Go之generate
- 异地恋中,逐渐适应一个人到底意味着什么()
- 我眼中的佛系经纪人
- 《魔法科高中的劣等生》第26卷(Invasion篇)发售
- “成长”读书社群招募
- 2020-04-07vue中Axios的封装和API接口的管理