shiro-Authentication (Authentication)

Apache Shiro is a powerful and easy-to-use Java security framework that provides authentication, authorization, encryption, and session management capabilities to provide security for any application. This article mainly introduces the identity authentication function in Shiro, as follows: 



 This article refers to the official documentation of Apache Shiro: http://shiro.apache.org/authentication.html

1. Authenticating Subjects

  Subject The authentication body contains two pieces of information:

Principals: Identity. Can be username, email, mobile phone number, etc., used to identify a login subject; 
Credentials: Credentials. Common passwords, digital certificates and so on.

  In Shiro, you can specify an authentication subject in the .ini file, or you can get it from the database. Here we use the .ini file to write a simple authentication subject:

[users]
csdn1=12345
csdn2=12345

 It can represent two users, the accounts are csdn1 and csdn2, and the passwords are both 12345. As for how to use this file, I will introduce it in an example later. 

  The method of validating a subject can be effectively subdivided into three distinct steps:

Step 1: Collect the identity and credentials submitted by the subject; 
Step 2: Submit the identity and credentials; 
Step 3: If the submission is successful, allow access, otherwise retry authentication or block access. 
Step 4: Exit

  Here's how the API in Shiro reflects the above steps:

//Step1: Collect the Subject's principals and credentials
//Get a token based on username and password
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
//token.setRememberMe(true); //Optional

 

 

  In Step1, we use UsernamePasswordToken, which supports the most commonly used username/password authentication methods. This is Shiro's org.apache.shiro.authc.AuthenticationToken interface, an implementation of the base interface used by Shiro's authentication system on behalf of submitted principals and credentials. The username and password are verified with the corresponding identities and credentials in the Subject authentication body. Of course, you can also remember the user, this is optional, about RememberMe will be introduced in subsequent articles.

 

//Step2: Submit the principals and credentials
// get the currently executing user
Subject currentUser = SecurityUtils.getSubject();
//to authenticate
currentUser.login(token);

 

  In Step 2, first obtain the currently executing user through the SecurityUtils tool class, and then perform identity authentication. This authentication will refer to the Subject body in the ini file (of course, it actually refers to the information in the database). In the following sample program can be seen.

 

//Step3: Handling Success or Failure
try {
    currentUser.login(token);
} catch ( AuthenticationException ae ) {
    //unexpected error?
    // Trade error
}
//No problems, continue on as expected...

 

 

  In Step 3, we need to process correct or incorrect results according to the authentication results, so we need to wrap currentUser.login(token) with try/catch.

//Step4: Logging out
currentUser.logout();

  与认证相反的是释放所有已知的确定的状态。当主体完成与应用程序交互,可以调用subject.logout()放弃所有的身份信息,subject.logout()会删除所有身份信息以及他们的会话(这里的会话指的是Shiro中的会话)。

2. 认证过程(Authentication Sequence)

 

上文介绍了认证主体,以及从代码的角度来分析了一下身份认证过程。下面来看一下在身份认证中,Shiro里面都干了些啥。图出自官方文档: 

 

 

        Step1:应用程序代码在调用Subject.login(token)方法后,传入代表最终用户的身份和凭证构造的AuthenticationToken实例token。 

  Step2:将Subject实例委托给应用程序的SecurityManager(Shiro的安全管理)通过调用securityManager.login(token)来开始实际的认证工作。这里开始真正的认证工作了。 
  Step3,4,5:然后SecurityManager就会根据具体的reaml去进行安全认证了。 
  这个realm到底是啥呢?realm就是一个域,Shiro就是从realm中获取验证数据的,也就是我们写在.ini文件中的东西,当然了,这个realm有很多种,如text realm、jdbc realm、jndi realm等,text realm比较简单,这一节主要总结一下jdbc realm的使用,text realm也会提到。

3. 身份认证示例

pom.xml中的包如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>demo.shiro</groupId>
  <artifactId>Shiro02</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>Shiro02</name>
  <description>Shiro02</description>
  <build/>

  <dependencies>
    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-core</artifactId>
        <version>1.2.5</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.21</version>
    </dependency>
    <dependency>
        <groupId>c3p0</groupId>
        <artifactId>c3p0</artifactId>
        <version>0.9.1.2</version>
    </dependency>
    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>1.2</version>
    </dependency>
    <dependency>
    <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.38</version>
    </dependency>
  </dependencies>
</project>

 log4j.properties文件如下:

 

log4j.rootLogger=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m %n
# General Apache libraries
log4j.logger.org.apache=WARN
# Spring
log4j.logger.org.springframework=WARN
# Default Shiro logging
log4j.logger.org.apache.shiro=TRACE
# Disable verbose logging
log4j.logger.org.apache.shiro.util.ThreadContext=WARN
log4j.logger.org.apache.shiro.cache.ehcache.EhCache=WARN

 

首先写一个shiro.ini文件,文件内容很简单,只放一个用户信息:

[users]

csdn=1234

 

然后开始写身份认证的java代码了,如下:

public class TextRealm {

    public static void main(String[] args) {
        // 读取配置文件,初始化SecurityManager工厂
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
        // 获取securityManager实例
        SecurityManager securityManager = factory.getInstance();
        // 把securityManager实例绑定到SecurityUtils
        SecurityUtils.setSecurityManager(securityManager);
        // 创建token令牌,用户名/密码
        UsernamePasswordToken token = new UsernamePasswordToken("csdn", "123");
        // 得到当前执行的用户
        Subject currentUser = SecurityUtils.getSubject();
        try{
            // 身份认证
            currentUser.login(token);   
            System.out.println("身份认证成功!");
        }catch(AuthenticationException e){
            e.printStackTrace();
            System.out.println("身份认证失败!");
        }
        // 退出
        currentUser.logout();
    }
}

 运行该程序就可以根据传入的参数和realm中的数据进行匹对,完成身份认证,从而打印认证成功,如果用户名和密码填写一个错误的,则会验证失败。 

  接下来再分析一下jdbc realm的写法,首先新建一个JdbcRealm.ini文件,如下:

 

[main]
#数据源选择的是c3p0
dataSource=com.mchange.v2.c3p0.ComboPooledDataSource
dataSource.driverClass=com.mysql.jdbc.Driver
dataSource.jdbcUrl=jdbc:mysql://localhost:3306/db_shiro
dataSource.user=root
dataSource.password=root

#定义一个jdbc的realm,取名为jdbcRealm
jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm

#jdbcRealm中有个属性是dataSource,选择我们上边定义的dataSource
jdbcRealm.dataSource=$dataSource

#SecurityManager中的realm选择上面定义的jdbcRealm
securityManager.realms=$jdbcRealm

 

然后需要准备数据库的数据,我新建了一个数据库db_shiro,里面有个users表,两个字段username和password,我就放了三个数据用来测试的,如下: 

 

 

 然后写JdbcRealm.java代码,和上面的一样的,只不过读取的配置文件不同

 

 

public class JdbcRealm {

    public static void main(String[] args) {
        // 读取配置文件,初始化SecurityManager工厂
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:jdbc_realm.ini");
        // 获取securityManager实例
        SecurityManager securityManager = factory.getInstance();
        // 把securityManager实例绑定到SecurityUtils
        SecurityUtils.setSecurityManager(securityManager);
        // 得到当前执行的用户
        Subject currentUser = SecurityUtils.getSubject();
        // 创建token令牌,用户名/密码
        UsernamePasswordToken token = new UsernamePasswordToken("倪升武2", "123");
        try{
            // 身份认证
            currentUser.login(token);   
            System.out.println("身份认证成功!");
        }catch(AuthenticationException e){
            e.printStackTrace();
            System.out.println("身份认证失败!");
        }
        // 退出
        currentUser.logout();
    }
}

 

 这样Shiro就会根据这个jdbc realm从数据库中获取验证数据对传入的参数进行身份验证,验证通过则打印出通过的语句,否则不予通过。这就是Shiro中简单的身份认证,下一节将总结一下Shiro中的权限认证,即授权。

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326117131&siteId=291194637