shiro的认证

Posted 健康平安的活着

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了shiro的认证相关的知识,希望对你有一定的参考价值。

一  认证

1.1 认证

身份认证,就是判断一个用户是否为合法用户的处理过程。最常用的简单身份认证方式是系统通过核对用户输入的用户名和口令,看其是否与系统中存储的该用户的用户名和口令一致,来判断用户身份是否正确。

1.2 认证角色中的对象

  • Subject:主体

访问系统的用户,主体可以是用户、程序等,进行认证的都称为主体;

  • Principal:身份信息

是主体(subject)进行身份认证的标识,标识必须具有唯一性,如用户名、手机号、邮箱地址等,一个主体可以有多个身份,但是必须有一个主身份(Primary Principal)。

  • credential:凭证信息

是只有主体自己知道的安全信息,如密码、证书等

1.3 认证流程

二 简单认证流程

2.1 pom文件

<dependency>
  <groupId>org.apache.shiro</groupId>
  <artifactId>shiro-core</artifactId>
  <version>1.5.3</version>
</dependency>

2.2 shiro信息配置文件

创建shiro.ini配置文件,放到resource文件目录下,写入的内容,如下:

2.3  验证代码

public class TestAuthenticator {
    public static void main(String[] args) {
        //创建securityManager
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        defaultSecurityManager.setRealm(new IniRealm("classpath:shiro.ini"));
        //将安装工具类中设置默认安全管理器
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        //获取主体对象
        Subject subject = SecurityUtils.getSubject();
        //创建token令牌
        UsernamePasswordToken token = new UsernamePasswordToken("xiaochen1", "123");
        try {
            subject.login(token);//用户登录
            System.out.println("登录成功~~");
        } catch (UnknownAccountException e) {
            e.printStackTrace();
            System.out.println("用户名错误!!");
        }catch (IncorrectCredentialsException e){
            e.printStackTrace();
            System.out.println("密码错误!!!");
        }

    }
}

执行结果:

将用户配置文件中正确的用户:

 

public class TestAuthenticator {
    public static void main(String[] args) {
        //创建securityManager
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        defaultSecurityManager.setRealm(new IniRealm("classpath:shiro.ini"));
        //将安装工具类中设置默认安全管理器
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        //获取主体对象
        Subject subject = SecurityUtils.getSubject();
        //创建token令牌
        UsernamePasswordToken token = new UsernamePasswordToken("lisi", "123");
        try {
            subject.login(token);//用户登录
            System.out.println("登录成功~~");
        } catch (UnknownAccountException e) {
            e.printStackTrace();
            System.out.println("用户名错误!!");
        }catch (IncorrectCredentialsException e){
            e.printStackTrace();
            System.out.println("密码错误!!!");
        }

    }
}

执行结果:

2.4 源码的流程

认证:

      1.最终执行用户名比较 SimpleAccountRealm
        doGetAuthenticationInfo 在这个方法中完成用户名的校验
      2.最终密码校验是在AuthenticationRealm中
      assertCredentialsMatch
 总结:AuthenticatingRealm 认证的realm DoGetAuthenticationInfo方法
        AuthorizatingRealm  授权realm   DoGetAuthorizationInfo方法

 三 Ream

3.1 reaml的作用

上边的程序使用的是Shiro自带的IniRealm,IniRealm从ini配置文件中读取用户的信息,大部分情况下需要从系统的数据库中读取用户信息,所以需要自定义realm。

shiro提供的realm如下图所示:

2.认证源码使用的SimpleAccountRealm

SimpleAccountRealm的部分源码中有两个方法一个是 认证 一个是 授权, (AuthenticatingReaml有DoGetAuthenticationInfo()方法,AuthorizatingRealm有DoGetAuthorizationInfo()方法,AuthorizatingRealm继承AuthenticatingReaml,则同时具有了DoGetAuthenticationInfo()和DoGetAuthorizationInfo()两个方法,而SimpleAccountRealm继承AuthorizatingRealm,则SimpleAccountRealm同样具有DoGetAuthenticationInfo()和DoGetAuthorizationInfo()两个方法的功能

3.2 自定义realm 

1.调用类:

package com.shiro.ljf.demo.test;

import com.shiro.ljf.demo.sptshirodemo.shiro.CustomerDefineRealm;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;

/**
 * 使用自定义realm
 */
public class TestCustomerRealmAuthenticator {
    public static void main(String[] args) {

        //创建securityManager
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        //设置自定义realm
        defaultSecurityManager.setRealm(new CustomerDefineRealm());
        //将安全工具类设置安全工具类
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        //通过安全工具类获取subject
        Subject subject = SecurityUtils.getSubject();
        //创建token
        UsernamePasswordToken token = new UsernamePasswordToken("xiaochen", "123");

        try {
            subject.login(token);
            System.out.println(subject.isAuthenticated());
        } catch (UnknownAccountException e) {
            e.printStackTrace();
            System.out.println("用户名错误");
        } catch (IncorrectCredentialsException e) {
            e.printStackTrace();
            System.out.println("密码错误");
        }


        //认证用户进行授权
        if(subject.isAuthenticated()){

            //1.基于角色权限控制
            System.out.println(subject.hasRole("admin"));


        }


    }
}

2.自定义CustomerDefineRealm

package com.shiro.ljf.demo.sptshirodemo.shiro;

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;

/**
 * @ClassName: CustomerDefineRealm
 * @Description: TODO 自定义realm实现 将认证|授权数据的来源转为数据库的实现
 * @Author: liujianfu
 * @Date: 2021/05/29 19:23:30 
 * @Version: V1.0
 **/
public class CustomerDefineRealm extends AuthorizingRealm {
    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("==================");
        return null;
    }

    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //在token中获取用户名
        String principal = (String) token.getPrincipal();
        System.out.println(principal);
        //根据身份信息使用jdbc mybatis查询相关数据库
        if("lisi".equals(principal)){
            //参数1:返回数据库中正确的用户名   //参数2:返回数据库中正确密码  //参数3:提供当前realm的名字 this.getName();
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(principal,"123",this.getName());
            return simpleAuthenticationInfo;
        }
        return null;
    }
}

3.调试

4. 改为正确的用户名

验证通过后,调用

System.out.println(" hou:"+subject.isAuthenticated());  则会返回true。

 

以上是关于shiro的认证的主要内容,如果未能解决你的问题,请参考以下文章

debug代码解析shiro认证流程

Shiro权限管理6.Shiro认证思路分析

Apache Shiro 使用手册Shiro 认证

Shiro01 功能点框图架构图身份认证逻辑身份认证代码实现

快速理解shiro的认证

全栈编程系列SpringBoot整合Shiro(含KickoutSessionControlFilter并发在线人数控制以及不生效问题配置启动异常No SecurityManager...)(代码片段