shrio自己内置一些密码校验规则,也可以实现简单的自定义,比如算法类型,hash次数等,但是有时候我们有一些比较特殊的密码校验规则,需要自定义来实现

1.shiro的密码校验是如何做的?

我们在登录方法内做完参数校验,验证码匹配等基本工作之后,都会将用户名和密码通过subject.login(auth) 传入框架来做用户匹配,但是,是和什么地方的数据进行匹配呢?

UsernamePasswordToken auth = new UsernamePasswordToken(username, password,false);
Subject subject = SecurityUtils.getSubject();
subject.login(auth);

答案就是在自定义的Realm中定义的AuthenticationInfo 进行匹配

可以通过shiro框架源码AuthenticatingRealm类的 assertCredentialsMatch方法看到,传入了两个参数,token就是我们登陆方法中传入的UsernamePasswordToken对象,而info就是我们在钉钉一Realm中doGetAuthenticationInfo 方法中定义的info对象。

shiro框架校验:

//shiro源码--用户信息认证 对比protected void assertCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) throws AuthenticationException {CredentialsMatcher cm = this.getCredentialsMatcher();if (cm != null) {//信息认证if (!cm.doCredentialsMatch(token, info)) {String msg = "Submitted credentials for token [" + token + "] did not match the expected credentials.";throw new IncorrectCredentialsException(msg);}} else {throw new AuthenticationException("A CredentialsMatcher must be configured in order to verify credentials during authentication.  If you do not wish for credentials to be examined, you can configure an " + AllowAllCredentialsMatcher.class.getName() + " instance.");}}

这里需要弄清楚 doGetAuthenticationInfo和doGetAuthorizationInfo  前者是定义用户认证信息的,而后者是定义用户权限信息,有点容易混淆。

2.实现自定义Realm:

public class ShiroFileRealm extends AuthorizingRealm implements InitializingBean {@Autowiredpublic void setCredentialsDigest(CredentialsDigest credentialsDigest) {this.credentialsDigest = credentialsDigest;}@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {UsernamePasswordToken token = (UsernamePasswordToken) authcToken;User user = userService.getUser(token.getUsername());if (user != null) {//此处返回的对象就是上面的inforeturn new SimpleAuthenticationInfo(new ShiroUser(user.getUsername()), user.getPassword(),getName());}return null;}@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {//自定义用户权限SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();return info;}/*** 设定密码校验规则*/public void afterPropertiesSet() throws Exception {CredentialsMatcher matcher = new CredentialsMatcherAdapter(credentialsDigest);setCredentialsMatcher(matcher);}}

上面代码中SimpleAuthenticationInfo 就是返回的用户认证信息,也是框架中做对比的info

好了,认证流程基本弄明白,我们就需要实现自定义校验,怎么做呢?

3.实现自定义CredentialsMatcher 认证类

/*** 设定密码校验规则*/public void afterPropertiesSet() throws Exception {CredentialsMatcher matcher = new CredentialsMatcherAdapter(credentialsDigest);//设置自定义的用户信息认证类setCredentialsMatcher(matcher);}

关键就是这里,CredentialsMatcherAdapter 是个实现了CredentialsMatcher接口的自定义类

public class CredentialsMatcherAdapter implements CredentialsMatcher {private CredentialsDigest credentialsDigest;public CredentialsMatcherAdapter(CredentialsDigest credentialsDigest) {Assert.notNull(credentialsDigest, "The argument must not be null");this.credentialsDigest = credentialsDigest;}public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {String plainCredentials, credentials;byte[] saltByte = null;plainCredentials = toStringCredentials(token.getCredentials());if (info instanceof SaltedAuthenticationInfo) {ByteSource salt = ((SaltedAuthenticationInfo) info).getCredentialsSalt();if (salt != null) saltByte = salt.getBytes();}credentials = toStringCredentials(info.getCredentials());if(saltByte != null){return credentialsDigest.matches(credentials, plainCredentials, saltByte);}return credentialsDigest.matches(credentials, plainCredentials);}private static String toStringCredentials(Object credentials) {if (credentials == null) {return null;} else if (credentials instanceof String) {return (String) credentials;} else if (credentials instanceof char[]) {return new String((char[]) credentials);} else {throw new IllegalArgumentException("credentials only support String or char[].");}}
}

doCredentialsMatch 方法就是实现用户信息校验 对比的方法,上面shiro框架的校验流程(cm.doCredentialsMatch(token, info))就会走到我们这里的方法中

上面credentialsDigest.matches(credentials, plainCredentials); 是我自己实现的密码比较方法

有加盐模式和无盐模式

贴出来给大家参考下

接口

public interface CredentialsDigest {String digest(String plainCredentials, byte[] salt);boolean matches(String credentials, String plainCredentials, byte[] salt);boolean matches(String credentials, String plainCredentials);
}

实现类

public  abstract class HashCredentialsDigest implements CredentialsDigest {static final int HASH_ITERATIONS = 1024;public String digest(String plainCredentials, byte[] salt) {if (StringUtils.isBlank(plainCredentials)) return null;byte[] hashPassword = digest(plainCredentials.getBytes(StandardCharsets.UTF_8), salt);return Hex.encodeHexString(hashPassword);}public boolean matches(String credentials, String plainCredentials, byte[] salt) {if (StringUtils.isBlank(credentials) && StringUtils.isBlank(plainCredentials)) return true;return StringUtils.equals(credentials, digest(plainCredentials, salt));}public boolean matches(String credentials, String plainCredentials) {if (StringUtils.isBlank(credentials) && StringUtils.isBlank(plainCredentials)) return true;return StringUtils.equals(credentials, plainCredentials);}protected abstract byte[] digest(byte[] input, byte[] salt);
}

主要的自定义代码就在CredentialsMatcherAdapter和CredentialsDigest中。。。

Shrio框架实现自定义密码校验规则相关推荐

  1. JS密码校验规则前台验证(不能连续字符(如123、abc)连续3位或3位以上)(不能相同字符(如111、aaa)连续3位或3位以上)

    密码必须为8到16位且必须包含数字和字母 密码必须包含特殊字符[_&#%] 不能连续字符(如123.abc)连续3位或3位以上 不能相同字符(如111.aaa)连续3位或3位以上 /*** 外 ...

  2. 自定义公式校验规则、常用的JavaScript正则公式合法校验、自定义公式合集、前端校验规则、字符串校验

    vue开发中,会使用到自定义公式校验合法性,判断公式是否符合逻辑, 整理个人使用过的自定义公式页面保存时对输入的字符串进行校验的一套规则 (文章最后有完整代码) 目录 1. 正则判断 2. 校验数字( ...

  3. 正则-补充(不能纯数字,和一般密码校验规则)

    附个牛逼的链接: https://www.cnblogs.com/cexm/p/7737538.html 一般密码的校验: 代码段: computed: {resetRules () {var val ...

  4. EasyUI 扩展自定义EasyUI校验规则 验证规则(常用的)

    转自:http://blog.csdn.net/pqszq1314/article/details/25896163 例如 校验输入框只能录入0-1000之间 最多有2位小数的数字 表单<inp ...

  5. JS密码校验规则前台验证(不能连续字符(如123、abc)连续3位或3位以上)(不能相同字符(如111、aaa)连续3位或3位以上)...

    密码必须为8到16位且必须包含数字和字母 密码必须包含特殊字符[_&#%] 不能连续字符(如123.abc)连续3位或3位以上 不能相同字符(如111.aaa)连续3位或3位以上 /*** 外 ...

  6. EasyUI 扩展自定义EasyUI校验规则 验证规则

    $.extend($.fn.validatebox.defaults.rules, { CHS: { validator: function (value, param) { return /^[\u ...

  7. antd form rules字数限制_【React】antd的form表单的自定义校验规则的用法

    在用到antd的Form组件的时候,可能会用到自定义的规则,以我的项目为例:在输入名称的时候需要请求接口,校验的内容是后台返回的内容,所以这个时候需要用到自定义的校验规则 屏幕快照 2019-06-1 ...

  8. java生成密码规则 形似校验规则

    最近接到一个需求,按照一定的规则自动生成密码,并且要校验密码的规则和形似规则,网上搜了一下没找到我想到的形似规则处理方式,只能自己动手尝试写写了. 密码规则: 口令至少由8-20位大写字母.小写字母. ...

  9. 使用profile的PASSWORD_VERIFY_FUNCTION参数实现自定义的密码验证规则

    profile的PASSWORD_VERIFY_FUNCTION参数,允许我们在创建用户或者更改用户 密码时实施自定义的密码验证规则. 1.首先,我们需要创建一个自己的实现密码验证规则的函数,该函数必 ...

最新文章

  1. 微擎获取openid_微擎中使用微信之门接口,让订阅号也能直接以网页的方式获取OpenID...
  2. TensorFlow练习9: 生成妹子图(PixelCNN)
  3. mybatis修改mysql变量_Java通过MyBatis框架对MySQL数据进行增删查改的基本方法
  4. 移植wpa_supplicant 2.2问题
  5. Java元组Tuple介绍与使用
  6. Tableau的简单数据可视化操作
  7. 中国大数据与智能计算产业联盟“开源软件工作委员会”成立会议在京召开
  8. UBUNTU设置SSH通过密钥登陆
  9. Java程序设计以及实验指导 实验笔记
  10. 等差素数列(java)
  11. html input trim,javascript – jQuery:$.trim()在input.val()中的单词之间的空格
  12. 机器学习指标_20种流行的机器学习指标第2部分排名统计指标
  13. 六轴机械臂DIY(二)机械本体分析设计
  14. 企业信息化互联网转型“生死劫”
  15. 一种通用的Qt数据库接口操作方法
  16. 第一部分 数理逻辑 第三章 命题逻辑的推理理论
  17. 将数字金额转换为中文大写金额
  18. 如何查看linux内核版本
  19. QVector常见使用方法
  20. 7款易上手C语言编程软件推荐

热门文章

  1. 德国工业考察之拜访3S公司
  2. Linux下类迅雷的下载神器-uGet 2.0
  3. 守一隅静美,醉一域风情
  4. CSS案例 • 【第7章 横幅广告滑块】
  5. 查看重做日志缓冲区大小
  6. Error Code: 1046. No database selectedSelect the default DB to be used by double-clicking its name i
  7. stata行业变量怎么赋值_邹军:怎么通过宏程序实现刀具寿命管理(二)
  8. openGL之API学习(一八七)gl_Vertex
  9. JARVIS 手机监控局域网内PC
  10. OROCOS之BFL(1)—— Linux环境搭建篇