前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >②【Shiro】Shiro登录认证、自定义Realm

②【Shiro】Shiro登录认证、自定义Realm

作者头像
.29.
发布2024-03-21 10:51:41
950
发布2024-03-21 10:51:41
举报
文章被收录于专栏:个人技术博客个人技术博客

个人简介:Java领域新星创作者;阿里云技术博主、星级博主、专家博主;正在Java学习的路上摸爬滚打,记录学习的过程~ 个人主页:.29.的博客 学习社区:进去逛一逛~

②【Shiro】Shiro登录认证、自定义Realm

1. 登录认证相关概念

  • 身份认证:一般需要提供身份ID等一些表示信息来表明登陆者身份,如提供email,用户名/密码来证明。
  • 在Shiro框架中,用户需要提供principals(身份)credentials(证明)给shiro,从而shiro对用户进行身份验证。
  • principals(身份):是主体的标识属性,可以是任何属性,如:用户名、email等,保证唯一即可。一份主体可以有多个principals,但是只有一个Primary principals,一般是用户名/邮箱/手机号。
  • credentials(证明):证明/凭证,是只有主体知道的安全值,如:密码、数字证书。
  • 最常见的principals和credentials组合就是:用户名/密码。

2. 登录认证 编码流程

基本流程

  1. 收集用户身份/凭证,即如用户名/密码;
  2. 调用 Subject.login() 进行登录,如果失败将得到对应的AuthenticationException异常,可根据异常提示用户错误信息;否则登录成功
  3. 创建自定义的 Realm 类,继承 org.apache.shiro.realm.AuthenticatingRealm类,实现 doGetAuthenticationInfo() 方法

3. 登录认证案例

导入坐标

代码语言:javascript
复制
<!-- shiro-core -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.9.0</version>
        </dependency>

        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>

配置ini文件

代码语言:javascript
复制
# Shiro获取权限相关信息可以通过数据库获取,也可以通过ini文件获取

# 配置账户密码信息
[users]
userA = 123a
userB = 123b

测试案例

代码语言:javascript
复制
/**
 * @author .29.
 * @create 2024-03-16 16:54
 */
public class shiroRun {
    public static void main(String[] args){
        //1. 初始化获取安全管理器SecurityManager
        IniSecurityManagerFactory factory = new IniSecurityManagerFactory("classpath:Shiro.ini");
        SecurityManager securityManager = factory.getInstance();
        SecurityUtils.setSecurityManager(securityManager);
        //2. 获取Subject对象
        Subject subject = SecurityUtils.getSubject();
        //3. 创建token对象,web应用用户名密码从页面传递
        UsernamePasswordToken token = new UsernamePasswordToken("userA", "123a");
        //如果希望应用程序在用户返回时记住用户,可以使用令牌的setRememberMe()方法,并设置参数为true
        token.setRememberMe(true);
        //4. 完成登录
        //你可以接受该方法调用并将其包装在 try/catch 块中,如果你想处理它们并做出相应的反应,你可以捕获各种异常。
        try{
            subject.login(token);
            System.out.println("登陆成功!");
        }catch (UnknownAccountException e){
            e.printStackTrace();
            System.out.println("用户不存在!");
        }catch (IncorrectCredentialsException e){
            e.printStackTrace();
            System.out.println("密码错误!");
        }catch (AuthenticationException ae){
            //这个块捕获了所有的认证异常,
            //表达的意思是,以此类推,你可以通过捕获异常的方式来处理逻辑
        }
    }
}

4. 登陆认证 执行流程

  1. 首先调用 Subject.login(token) 进行登录,其会自动委托给 SecurityManager
  2. SecurityManager 负责真正的身份验证逻辑;它会委托给 Authenticator 进行身份验证;
  3. Authenticator可能会委托给相应的 AuthenticationStrategy 进行多 Realm 身份验证,默认 ModularRealmAuthenticator 会调用 AuthenticationStrategy 进行多 Realm身份验证;
  4. Authenticator 会把相应的 token传入 Realm,从 Realm 获取身份验证信息,如果没有返回/抛出异常 就表示身份验证失败了。此处可以配置多个Realm,将按照相应的顺序及策略进行访问。

5. 自定义登录认证、Realm

  • Shiro 默认的登录认证是不带加密的,如果想要实现加密认证需要自定义登录认证,自定义 Realm。

导入坐标

代码语言:javascript
复制
<!-- shiro-core -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.9.0</version>
        </dependency>

        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>

自定义Realm进行登录认证

代码语言:javascript
复制
/**
 * @author .29.
 * @create 2024-03-16 19:08
 * 1.自定义Realm进行登录认证,配置好后Shiro的Subject.login()方法底层会调用该类的认证方法完成登录认证
 * 2.想要自定义的 realm 生效,需要在 ini 文件或 Springboot配置文件在中进行相关配置配置
 * 3.该方法只是获取进行对比的信息,认证逻辑还是按照 Shiro 的底层认证逻辑完成认证
 */
public class myRealm extends AuthenticatingRealm {

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //1. 通过token获取身份信息
        String principal = authenticationToken.getPrincipal().toString();
        //2. 通过token获取凭证信息
        String credentials = new String((char[]) authenticationToken.getCredentials());
        System.out.println("认证用户信息:"+principal+"---"+credentials);

        //3. 获取数据库中存储的用户信息
        if(principal.equals("userA")){
            //3.1模拟从数据库中获取到MD5加盐嵌套3次加密的密码
            String pwd = "e8e2ea5deb7e981462ab88c2b7e3f19a";
            //3.2创建封装了校验逻辑的对象,将需要校验的数据传进去
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(
                    authenticationToken.getPrincipal()//身份
                    , pwd//数据库中存放的密码
                    , ByteSource.Util.bytes("salt")//MD5加盐的“盐”
                    , authenticationToken.getPrincipal().toString()
            );
            return info;//返回封装了校验逻辑的对象
        }

        return null;
    }
}

配置ini文件

代码语言:javascript
复制
# Shiro获取权限相关信息可以通过数据库获取,也可以通过ini文件获取

#添加配置,配置解密MD5的循环次数,配置使用自定义的Realme进行登录校验,
[main]
md5CredentialsMatcher=org.apache.shiro.authc.credential.Md5CredentialsMatcher
md5CredentialsMatcher.hashIterations=3

myrealm=com.to9.test.myRealm
myrealm.credentialsMatcher=$md5CredentialsMatcher
securityManager.realms=$myrealm

# 配置账户密码信息,密码是"123456789"MD5加盐加密3次的结果,盐为"salt"
[users]
userA = e8e2ea5deb7e981462ab88c2b7e3f19a

测试案例

代码语言:javascript
复制
/**
 * @author .29.
 * @create 2024-03-16 16:54
 */
public class shiroRun {
    public static void main(String[] args){
        //1. 初始化获取安全管理器SecurityManager
        IniSecurityManagerFactory factory = new IniSecurityManagerFactory("classpath:Shiro.ini");
        SecurityManager securityManager = factory.getInstance();
        SecurityUtils.setSecurityManager(securityManager);
        //2. 获取Subject对象
        Subject subject = SecurityUtils.getSubject();
        //3. 创建token对象,web应用用户名密码从页面传递
        UsernamePasswordToken token = new UsernamePasswordToken("userA", "123456789");
        //如果希望应用程序在用户返回时记住用户,可以使用令牌的setRememberMe()方法,并设置参数为true
        token.setRememberMe(true);
        //4. 完成登录
        //你可以接受该方法调用并将其包装在 try/catch 块中,如果你想处理它们并做出相应的反应,你可以捕获各种异常。
        try{
            subject.login(token);
            System.out.println("登陆成功!");
        }catch (UnknownAccountException e){
            e.printStackTrace();
            System.out.println("用户不存在!");
        }catch (IncorrectCredentialsException e){
            e.printStackTrace();
            System.out.println("密码错误!");
        }catch (AuthenticationException ae){
            //这个块捕获了所有的认证异常,
            //表达的意思是,以此类推,你可以通过捕获异常的方式来处理逻辑
        }
    }
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2024-03-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ②【Shiro】Shiro登录认证、自定义Realm
    • 1. 登录认证相关概念
      • 2. 登录认证 编码流程
        • 3. 登录认证案例
          • 4. 登陆认证 执行流程
            • 5. 自定义登录认证、Realm
            相关产品与服务
            多因子身份认证
            多因子身份认证(Multi-factor Authentication Service,MFAS)的目的是建立一个多层次的防御体系,通过结合两种或三种认证因子(基于记忆的/基于持有物的/基于生物特征的认证因子)验证访问者的身份,使系统或资源更加安全。攻击者即使破解单一因子(如口令、人脸),应用的安全依然可以得到保障。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档