文章目录
- 前言
- 一、解决办法
- 二、解决过程
- 1 为啥要改加密算法
- 2 找不到校验代码
- 总结
前言
若依是一套快速集成各种中间件的配套 Java 后端框架,本文旨在描述修改其登陆的加密算法。文章的大前提是后端框架是若依哈,不是的话可以跳过了~!
文章创作原因:系统针对登陆密码是密文存储,而在登陆时的校验规则却在登录方法没找到这块的代码,导致一开始修改时摸不着头。
提示:以下是本篇文章正文内容,下面案例可供参考
一、解决办法
先说解决办法,在 SecurityConfig 这个文件中将原有的加密算法的 bean 注释掉,然后创建自己的加密算法的 bean 就行,再将 authenticationProvider 方法设置密码加密的bean对象改成自己定义的方法即可。
/*** 强散列哈希加密实现*//*@Beanpublic BCryptPasswordEncoder bCryptPasswordEncoder() {return new BCryptPasswordEncoder();}*//*** 自定义加密算法* */@Beanpublic TestPasswordEncoder testPasswordEncoder() {return new TestPasswordEncoder();}/*** 身份认证接口*/@Beanpublic DaoAuthenticationProvider authenticationProvider() {DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();authProvider.setUserDetailsService(userDetailsService);authProvider.setPasswordEncoder(testPasswordEncoder());return authProvider;}
自定义的加密类需要实现org.springframework.security.crypto.password.PasswordEncoder,然后重写两个方法即可。
package com.demo.utils;import org.springframework.security.crypto.password.PasswordEncoder;public class TestPasswordEncoder implements PasswordEncoder {@Overridepublic String encode(CharSequence rawPassword) {return "";}@Overridepublic boolean matches(CharSequence rawPassword, String encodedPassword) {return false;}
}
顺便说明下,encode 方法是将参数加密成密文,matches 方法的第一个参数是未加密的参数,第二个参数是密文,不难理解方法的逻辑是将第一个参数在加密过后,与第二个参数进行比较,根据结果返回一个boolean。
当然,改完这个就完事了吗??No_No_No~
注意事项:
1 在修改密码的方法中,需要同步加密新密码,再入库保存;
2 新增用户时需要针对配置的默认密码也进行进行加密,,再入库保存;
3 如果有文件导入的方法创建用户,那么也需要针对密码进行加密;
4 建议对原来的加密类,再查询下是否有其他地方在引用,根据代码判断是否也需要修改;
后面是作者对整个过程的梳理,如果仅是修改加密算法,那么看到这里就可以了,如果能帮到大家,还需要大家的点赞收藏支持,这个真的很重要~~
二、解决过程
1 为啥要改加密算法
这个其实不难理解,因为甲方是一家 bank 公司,对加密有着严格要求,只是当我将这块都写完了才意识到一个问题,密文存储密码导致密码在数据库的字符串看起来就像是乱码一样,那他怎么知道我是否用了规定的加密算法呢?哈哈~开句玩笑,但是我确实不清楚甲方如何去验证这个。
2 找不到校验代码
这部分描述会附上代码,因为这块代码是若依框架自带的,所以不同的项目关于登录的代码几乎一样。
如前言所述,系统原来的校验逻辑是看不到的,只有一行代码
// 该方法会去调用UserDetailsServiceImpl.loadUserByUsernameauthentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
这行代码会校验密码,但是点进这个 authenticate 方法内部,发现这个方法本身是个接口,有多个实现
Authentication authenticate(Authentication authentication) throws AuthenticationException;
而这个方法内部的 new UsernamePasswordAuthenticationToken(username, password) 对应的构造函数也看不出校验逻辑
public UsernamePasswordAuthenticationToken(Object principal, Object credentials) {super(null);this.principal = principal;this.credentials = credentials;setAuthenticated(false);}
然后我也看了注释中提到的方法,发现也没有关于密码校验的逻辑
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {SysUser user = userService.selectUserByUserName(username);if (StringUtils.isNull(user)) {log.info("登录用户:{} 不存在.", username);throw new ServiceException("账号或密码错误");} else if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) {log.info("登录用户:{} 已被删除.", username);throw new ServiceException("账号或密码错误");} else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {log.info("登录用户:{} 已被停用.", username);throw new ServiceException("对不起,您的账号:" + username + " 已停用");}return createLoginUser(user);}public UserDetails createLoginUser(SysUser user) {return new LoginUser(user.getUserId(), user.getDeptId(), user, permissionService.getMenuPermission(user));}
所以单从代码去追溯源码,比较困难;正向解决不了问题,只能问百度了,在看了十几篇文章后发现,在系统 SecurityConfig 文件中,有关于加密算法对象的 bean,然后就自然而然的想把这个算法替换成自己的加密算法,然后就ok了。
总结
没什么好总结的,这是框架将密码校验的部分封装了,所以必需要一层层看源码才能直接解决问题,作者这属于走捷径,不推荐哈
如果文章正真的帮到你,或者让你知道了新知识,还希望大家多多~~~~~~~~~~~~~~点赞收藏!!!