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

在这里插入图片描述

个人简介: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. 登录认证案例

导入坐标

<!-- 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文件

# Shiro获取权限相关信息可以通过数据库获取,也可以通过ini文件获取

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

在这里插入图片描述


测试案例

/**
 * @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。

导入坐标

<!-- 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进行登录认证

/**
 * @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文件

# 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



测试案例

/**
 * @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){
            //这个块捕获了所有的认证异常,
            //表达的意思是,以此类推,你可以通过捕获异常的方式来处理逻辑
        }
    }
}





在这里插入图片描述

  • 17
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 24
    评论
以下是一个简单的Shiro自定义Realm代码示例: ``` import org.apache.shiro.authc.*; import org.apache.shiro.realm.*; public class MyRealm extends AuthorizingRealm { @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { // 这里实现权限角色信息的获取和设置,可以从数据库或其他数据源获取 SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); authorizationInfo.addRole("admin"); authorizationInfo.addStringPermission("user:create"); return authorizationInfo; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { // 这里实现用户认证,可以从数据库或其他数据源获取用户信息进行验证 String username = (String) token.getPrincipal(); String password = new String((char[]) token.getCredentials()); if (!"admin".equals(username)) { throw new UnknownAccountException(); } if (!"password".equals(password)) { throw new IncorrectCredentialsException(); } return new SimpleAuthenticationInfo(username, password, getName()); } } ``` 该自定义Realm实现了Shiro的`AuthorizingRealm`接口,实现了权限角色信息的获取和设置,以及用户认证的方法。其中,`doGetAuthorizationInfo`方法用于获取用户角色权限信息,并将其封装到`AuthorizationInfo`对象中返回;`doGetAuthenticationInfo`方法用于验证用户的身份和凭证信息,并将其封装到`AuthenticationInfo`对象中返回。在这个简单的示例中,认证信息被硬编码为了"admin"和"password",实际使用时应该从数据库或其他数据源中获取。
评论 24
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

.29.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值