Shiro入门学习---使用自定义Realm完成认证|练气中期

写在前面

在上一篇文章《shiro认证流程源码分析--练气初期》当中,我们简单分析了一下shiro的认证流程。不难发现,如果我们需要使用其他数据源的信息完成认证操作,我们需要自定义Realm继承AuthorizingRealm类,并实现两个方法,分别对应授权和认证。

在这一篇文章当中,我们将介绍如何自定义Realm对象,完成认证信息数据源的切换。

自定义Reaml

/**自定义Realm对象
 * @author 赖柄沣 bingfengdev@aliyun.com
 * @version 1.0
 * @date 2020/10/4 11:00
 */
public class MySqlRealm extends AuthorizingRealm {

    /**授权,今天暂不实现
     * @author 赖柄沣 bingfengdev@aliyun.com
     * @date 2020-10-04 11:01:50
     * @param principalCollection
     * @return org.apache.shiro.authz.AuthorizationInfo
     * @throws AuthenticationException
     * @version 1.0
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {

        return null;
    }

    /**认证
     * @author 赖柄沣 bingfengdev@aliyun.com
     * @date 2020-10-04 11:01:50
     * @param authenticationToken
     * @return org.apache.shiro.authz.AuthorizationInfo
     * @throws AuthenticationException
     * @version 1.0
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        // 1. 从token中获取用户名
        String principal = (String) authenticationToken.getPrincipal();

        //2. 根据用户名查询数据库(模拟)
        if (principal == "xiangbei") {
            AuthenticationInfo authInfo = new SimpleAuthenticationInfo("xiangbei","123",this.getName());
            return authInfo;
        }
        return null;
    }
}

在认证器中使用自定义Realm进行认证

/**认证管理器
 * @author 赖柄沣 bingfengdev@aliyun.com
 * @version 1.0
 * @date 2020/10/4 11:11
 */
public class CurrentSystemAuthenticator {
    private DefaultSecurityManager securityManager;
    public CurrentSystemAuthenticator() {
        //创建安全管理器
        securityManager = new DefaultSecurityManager();

        //设置自定义realm
        this.securityManager.setRealm(new MySqlRealm());

        //将安全管理器设置到安全工具类中
        SecurityUtils.setSecurityManager(securityManager);

    }

    public void authenticate(String username,String password){
        //获取当前登录主题
        Subject subject = SecurityUtils.getSubject();

        //生成toeken
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);

        //进行认证
        try {
            subject.login(token);
        }catch (UnknownAccountException | IncorrectCredentialsException e) {
            System.out.println("用户名或密码不正确");
        }


        //打印认证状态
        if (subject.isAuthenticated()){
            System.out.println(token.getPrincipal()+" 认证通过!");
        }else {
            System.out.println(token.getPrincipal()+" 认证未通过!");
        }


    }
}

进行测试

认证通过的情况

用例代码

/**测试认证
 * @author 赖柄沣 bingfengdev@aliyun.com
 * @version 1.0
 * @date 2020/9/21 0:49
 */
public class TestAuthenticator {
    private  Authenticator authenticator=null;

    @Before
    public void init() {
        authenticator = new Authenticator();
    }

    @Test
    public void testAuth(){

        authenticator.authenticate("xiangbei","123");
    }
}

输出

xiangbei 认证通过!

认证不通过的情况

认证不通过的情况在shiro当中分为几种情况,具体可以查看我的上一篇文章《shiro认证流程源码分析--练气初期》 关于shiro认证异常的分析,常用的有如下几种:

  1. 账户不正确(不存在)
  2. 密码错误
  3. 账户被锁定
  4. 密码过期

在实际项目中为了安全起见,账户不正确和密码错误统一返回“用户名或密码不正确”类似的的提示,避免造成账户泄露。

下面针对这种情况给予演示

用例代码

/**
 * @author 赖柄沣 bingfengdev@aliyun.com
 * @version 1.0
 * @date 2020/10/4 11:20
 */
public class AuthcTest {
    private CurrentSystemAuthenticator authenticator;
    @Before
    public void init() {
        this.authenticator = new CurrentSystemAuthenticator();
    }

    @Test
    public void testAuthc(){
        this.authenticator.authenticate("xiangbei","13");
    }
}

输出

用户名或密码不正确
xiangbei 认证未通过!

写在最后

这一篇文章主要是带领大家了解一下如何通过自定义Realm对象完成shiro认证数据源的切换。对于MySQL的集成,我们将在后面的文章当中集成SpringBoot时介绍。

下一篇文章将简单介绍shiro中的密码加密以及如何配置使用。

本文所涉及的代码下载地址:https://github.com/code81192/art-demo/tree/master/shiro-authc-mysql

posted @ 2020-10-06 23:31  __Ferryman  阅读(353)  评论(0编辑  收藏  举报