回顾

第一个shiro项目,里面的realm是框架自带的,原数据是ini文件里面的,也就是之前认证的时候,shiro框架会自己用默认的认证规则到ini文件里面进行认证。现在想要自己改认证的数据源,那么就需要自己写认证规则

自己写一个认证规则

/**
 *
 * 自定义的认证规则
 */
public class MyRealm extends AuthenticatingRealm {
   
     

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
   
     
        System.out.println("执行认证");
        //用户名//用户名(拿到前段传过来的用户名)
        String username = token.getPrincipal().toString();
        //密码(拿到前段传过来的密码)
        String pwd = new String((char[])token.getCredentials());
        System.out.println(username+"  "+pwd);
        //先从数据库查询select * from user where username=? 查看用户名是否存在

        if(username.equals("admin")){
   
     //假设用户名为admin时能从数据库中查询出来
            //根据之前查询出来的用户信息获取密码。假设查询出来的密码是pwd
            String password= "pwd";
            //此处需要注意,第二个参数是从数据库查询出来的密码,而不是传递过来的密码。
            //第三个参数自定义。但是尽量不重复了。常直接使用用户名当做realname名字。
            //token.getPrincipal() 这个是用户传过来的用户名
            AuthenticationInfo info = new SimpleAuthenticationInfo(token.getPrincipal(),password,"realmname");
            //shiro会判断从数据库查询出来的密码和客户端传递过来的密码是否一致。
            return info;
        }
        //返回null说明用户名不存在。
        return null;
    }
}

解释以上代码

我们自己写的认证规则,如果想要shiro框架认识,必须实现shiro框架里面的一个接口AuthenticatingRealm ,并且重写里面的方法doGetAuthenticationInfo(),在这个方法里面写自己的认证规则,这个方法的参数就是 token,这个token里面保存的就是前段传过来的用户名和密码。

在这个自己写的认证规则里面,自己查询数据库,和前段传过来的数据进行对比

将认证规则配置到shiro里面

修改配置文件

在配置文件中添加下面内容

 

[main]
myrealm=com.jing.MyRealm
securityManager.realms=$myrealm

测试结果:
在ShiroRun中修改用户名和密码,当用户名和密码为admin、pwd时可以正常登录。
此时无论shiro.ini是否配置了[users],都按照Realm中配置的逻辑进行比较用户名和密码。

凭证匹配器

前段用户传过来的密码是明文的,但是数据库里面的密码是md5加密之后的,所以我们要在自定义的认证规则里面,写加密相关的

1修改自定义Realm


AuthenticationInfo 的构造方法由三个参数变成四个参数的。
新增第三个参数表示加盐。
一般都是拿用户数据的id作为盐。
//密码必须是MD5加密后的密码
String password= "7614fd642608ca0755b78d2b2c352e19";
//假设id是从数据库中取出的id
Long id = 123L;
//第三个参数是加密的盐
AuthenticationInfo info = new SimpleAuthenticationInfo(token.getPrincipal(), password, ByteSource.Util.bytes(id+"") ,token.getPrincipal().toString());

以上改完认证规则,已经有了加密的盐,但是我们还没有设置用什么加密器进行加密,迭代的次数也没有。所以我们还要配置一下
在ini配置文件里面的【main】里面进行配置

2修改配置文件

在配置文件中配置凭证匹配器配置。

 

[main]
告诉shiro使用MD5加密
md5CredentialsMatcher=org.apache.shiro.authc.credential.Md5CredentialsMatcher
告诉shiro迭代加密两次
md5CredentialsMatcher.hashIterations=2
myrealm=com.jing.MyRealm
myrealm.credentialsMatcher=$md5CredentialsMatcher
securityManager.realms=$myrealm

以上配置之后,就告诉shiro,将用户传过来的密码使用MD5进行加密,并且迭代两次之后,和数据库里面的数据进行比较。

总结

subject.login(token);

代码执行到以上处,然后就到了自定义规则里面了,在自定义规则里面,从token里面拿出前段传过来的用户名和密码,然后根据用户名从数据库查一下,数据库里面有没有这个用户,有的话,拿出数据库里面存储的密码,代码就走到了

//第一个参数是用户传过来的用户名
//此处需要注意,第二个参数是从数据库查询出来的密码,
//而不是传递过来的密码。
// 第三个参数是加盐的字符串
//第四个参数自定义。但是尽量不重复了。
//常直接使用用户名当做realname名字。
AuthenticationInfo info = new SimpleAuthenticationInfo(token.getPrincipal(),password, ByteSource.Util.bytes(id),"realmname");
//shiro会判断从数据库查询出来的密码和客户端传递过来的密码是否一致。