身份验证
身份验证,即在应用中谁能证明他就是他本人。一般提供如他们的身份 ID 一些标识信息来表明他就是他本人,如提供身份证,用户名/密码来证明。
在 shiro 中,用户需要提供 principals (身份)和 credentials(证明)给 shiro,从而应用能验证用户身份:
principals:身份,即主体的标识属性,可以是任何东西,如用户名、邮箱等,唯一即可。一个主体可以有多个 principals,但只有一个 Primary principals,一般是用户名/密码/手机号。
credentials:证明/凭证,即只有主体知道的安全值,如密码/数字证书等。
最常见的 principals 和 credentials 组合就是用户名/密码了。接下来先进行一个基本的身份认证。
另外两个相关的概念是之前提到的 Subject 及 Realm,分别是主体及验证主体的数据源。
环境准备
pom.xml文件
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<spring.version>4.0.0.RELEASE</spring.version>
<slf4j.version>1.7.12</slf4j.version>
<log4j.version>1.2.14</log4j.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.2</version>
</dependency>
<!-- 日志文件管理包 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<!-- 格式化对象,方便输出日志 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
</dependencies>
日志文件
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
shiro.ini文件
[main]
#配置数据源
dataSource=com.alibaba.druid.pool.DruidDataSource
#数据库驱动
dataSource.driverClassName=com.mysql.jdbc.Driver
#数据库指定路径
dataSource.url=jdbc:mysql://localhost:3306/20190516shiro
#用户名
dataSource.username=root
#链接数据库密码
dataSource.password=123456
#设置realm
jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm.dataSource=$dataSource
#为了测试
dataSource1=com.alibaba.druid.pool.DruidDataSource
#数据库驱动
dataSource1.driverClassName=com.mysql.jdbc.Driver
#数据库指定路径
dataSource1.url=jdbc:mysql://localhost:3306/20190516shiro1
#用户名
dataSource1.username=root
#链接数据库密码
dataSource1.password=123456
#设置realm
jdbcRealm1=org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm1.dataSource=$dataSource1
#指定 securityManager 的 authenticator 实现
authenticator=org.apache.shiro.authc.pam.ModularRealmAuthenticator
securityManager.authenticator=$authenticator
#指定 securityManager.authenticator 的 authenticationStrategy (验证策略)
#AllSuccessfulStrategy:所有 Realm 验证成功才算成功,且返回所有 Realm 身份验证成功的认证信息,如果有一个失败就失败了。
#allSuccessfulStrategy=org.apache.shiro.authc.pam.AllSuccessfulStrategy
#FirstSuccessfulStrategy:只要有一个 Realm 验证成功即可,只返回第一个 Realm 身份验证成功的认证信息,其他的忽略;
#firstSuccessfulStrategy=org.apache.shiro.authc.pam.FirstSuccessfulStrategy
#AtLeastOneSuccessfulStrategy:只要有一个 Realm 验证成功即可,和 FirstSuccessfulStrategy不同,返回所有 Realm 身份验证成功的认证信息(默认)
atLeastOneSuccessfulStrategy=org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy
securityManager.authenticator.authenticationStrategy=$atLeastOneSuccessfulStrategy
#注入realm
securityManager.realms=$jdbcRealm,$jdbcRealm1
测试代码
/**
* @author Return
* @create 2019/5/16 16:10
*/
public class JdbcRealmDemo {
public static void main(String[] args) {
//获取的得到securityManager的工厂对象
Factory<SecurityManager> factory=new IniSecurityManagerFactory("classpath:shiro.ini");
//获取到securitymanager
SecurityManager securityManager = factory.getInstance();
//通过securityUtil工具类将得到的securityManager对象设置进去
SecurityUtils.setSecurityManager(securityManager);
//然后得到的一个subject的对象
Subject subject=SecurityUtils.getSubject();
//获取的token对象
UsernamePasswordToken token=new UsernamePasswordToken("xyr","123");
//进行登录(即身份验证)
try {
subject.login(token);
if (subject.isAuthenticated()){
System.out.println("身份验证通过!");
}else{
System.out.println("身份验证失败!");
}
} catch (AuthenticationException e) {
e.printStackTrace();
}
}
}