shiro使用自定义realm实现数据认证

自定义realm实现数据认证

在开发中,有时会与一些nosql或者其他地方保存的数据进行认证,这时候,shiro定义的那些realm类可能不能满足实际的功能需求,这时候我们可以通过自定义一个realm来沟通这些数据。实现认证和权限控制。

首先自定义一个realm,继承自AuthorizingRealm抽象类,并实现它的两个功能:

package com.yinhai.realm;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

/**
 * 自定义Realm
 */
public class CoustomRealm  extends AuthorizingRealm {
    //做授权管理的
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        return null;
    }

    //做认证的
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
         //拿到account
        String principal = (String) token.getPrincipal();

        if("zhangsan".equals(principal)){ //模拟在数据库中查找用户名的过程,如果找到有,则将用户名和密码返回,没有直接返回null
            //通过用户名在数据库中拿到正确的密码,我这里直接省略
            String password = "123456";
            //新建一个返回信息返回给manager,manager会根据正确的账户和密码自动匹配用户传递过来的账户和密码,参数3是当前realm的名称,底			    层会自动生成的。
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(principal, password, this.getName());
            return simpleAuthenticationInfo;
        }


        return null;
    }
}

然后就可以使用这个realm了:

package com.yinhai;

import com.yinhai.realm.CoustomRealm;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;

/**
 * 使用自定义realm进行认证测试
 */
public class CostumeRealmAuthTest {
    public static void main(String[] args) {
        DefaultSecurityManager securityManager = new DefaultSecurityManager();
        securityManager.setRealm(new CoustomRealm());
        SecurityUtils.setSecurityManager(securityManager);
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken zhangsan = new UsernamePasswordToken("zhangsan", "123456");
        try{
            subject.login(zhangsan);
            System.out.println(subject.isAuthenticated());
        }catch (Exception e){
            e.getMessage();
        }
    }
}

以上是普通的,明文密码匹配方式认证,如果要使用加密的话可以采用以下:

package com.yinhai.realm;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;

public class CostumeMD5Realm extends AuthorizingRealm {
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //拿到account
        String principal = (String) token.getPrincipal();

        if("zhangsan".equals(principal)){ //模拟在数据库中查找用户名的过程,如果找到有,则将用户名和密码返回,没有直接返回null
            //通过用户名在数据库中拿到正确的密码,我这里直接省略
            String password = "458e4c8450daf785d77e92c6d391e6a2";
            //新建一个返回信息返回给manager,manager会根据正确的账户和密码自动匹配用户传递过来的账户和密码,
            // 参数3是盐加密规则
            // 参数4是当前realm的名称,底层会自动生成的。
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(principal,
                    password,
                    ByteSource.Util.bytes("07?*xx"),
                    this.getName());
            return simpleAuthenticationInfo;
        }


        return null;
    }
}

使用:

package com.yinhai;

import com.yinhai.realm.CostumeMD5Realm;
import com.yinhai.realm.CoustomRealm;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;

public class CostumeMD5RealmAuthTest {
    public static void main(String[] args) {
        DefaultSecurityManager securityManager = new DefaultSecurityManager();
        CostumeMD5Realm costumeMD5Realm = new CostumeMD5Realm();
        //获取密码匹配器
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        //设置加密方式
        hashedCredentialsMatcher.setHashAlgorithmName("MD5");
        //设置hash散列次数
        hashedCredentialsMatcher.setHashIterations(512);
        //设置自定义realm的密码匹配器
        costumeMD5Realm.setCredentialsMatcher(hashedCredentialsMatcher);

        securityManager.setRealm(costumeMD5Realm);
        SecurityUtils.setSecurityManager(securityManager);
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken zhangsan = new UsernamePasswordToken("zhangsan", "123456");
        try{
            subject.login(zhangsan);
            System.out.println(subject.isAuthenticated());
        }catch (Exception e){
            e.getMessage();
        }
    }
}

上一篇:React -- 组件的生命周期 (这一篇就够了!!!)


下一篇:springboot shiro 跨域问题