junit学习并总结shiro的身份认证
shiro-身份认证
介绍:
验证主体Subject(会存入前端的账号/密码)是否存在于realm(后端数据源)中
code Implementation
demo
使用junit的shiro入门demo
新建项目
导入maven依赖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28<?xml version="1.0" encoding="UTF-8"?>
<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>com.xiaoruiit</groupId>
<artifactId>shiro-learn</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</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>
</dependencies>
</project>配置后端数据源
resources下新建shiro.ini文件
1
2
3[users]
zhang=123
wang=123notice:idea需要ini4idea插件,并配置。参考
junit测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.apache.shiro.util.ThreadContext;
import org.junit.After;
import org.junit.Assert;
import org.junit.Test;
import static org.junit.Assert.*;
public class LoginLogout {
@Test
public void testHelloword (){
//1、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
//2、得到SecurityManager实例 并绑定给SecurityUtils
SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
//3、得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证)
Subject subject = SecurityUtils.getSubject();
// 4.从前端传来的账号/密码
UsernamePasswordToken token = new UsernamePasswordToken("zhang","123");
try {
// 身份验证
subject.login(token);
} catch (AuthenticationException e){
// 认证失败
e.printStackTrace();
System.out.println("登录失败");
}
Assert.assertEquals(true, subject.isAuthenticated());// 断言用户已经登录
// 退出,会清理session
subject.logout();
}
@After
public void close(){
// 不执行可能影响第二次运行Test
ThreadContext.unbindSubject();
}
}
Singlon-Realm
从demo的3开始
新建MyRealm类实现Realm接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37import org.apache.shiro.authc.*;
import org.apache.shiro.realm.Realm;
/**
* @author hxr
* @Classname MyRealm
* @Description ToDo
*/
public class MyRealm implements Realm {
// 返回一个唯一的Realm名字
public String getName() {
return "myRealm";
}
//判断此Realm是否支持此Token
public boolean supports(AuthenticationToken authenticationToken) {
// 仅支持UsernamePasswordToken类型的Token
return authenticationToken instanceof UsernamePasswordToken;
}
//根据Token获取认证信息
public AuthenticationInfo getAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
// 获取用户名
String username = (String) authenticationToken.getPrincipal();
// 获取密码
String password = new String((char[])authenticationToken.getCredentials());
if (!"zhang".equals(username)){
throw new UnknownAccountException();// 用户名不存在
}
if (!"123".equals(password)){
throw new IncorrectCredentialsException();// 密码错误
}
// 认证成功,返回AutnenticationInfo信息
return new SimpleAuthenticationInfo(username, password, getName());
}
}配置MyRealm
resource下新建shiro-realm文件
1
2
3
4
5[main]
#声明一个realm
myRealm = com.xiaoruiit.shiro.config.MyRealm
#指定securityManager的realms实现
securityManager.realms=$myRealmjunit测试
增加一个测试方法,修改shrio-reaml.ini即可
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18@Test
public void testSingleRealm(){
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-realm.ini");
SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("zhang","123");
try {
subject.login(token);
} catch (AuthenticationException e){
// 认证失败
e.printStackTrace();
System.out.println("登录失败");
}
Assert.assertEquals(true, subject.isAuthenticated());// 断言用户已经登录
subject.logout();
}
JDBC-Realm
建立在在demo的基础上
导入数据库依赖
1
2
3
4
5
6
7
8
9
10<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.25</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>0.2.23</version>
</dependency>在mysql中新建库shiro
新建三个表+1条user信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30drop database if exists shiro;
create database shiro;
use shiro;
create table users (
id bigint auto_increment,
username varchar(100),
password varchar(100),
password_salt varchar(100),
constraint pk_users primary key(id)
) charset=utf8 ENGINE=InnoDB;
create unique index idx_users_username on users(username);
create table user_roles(
id bigint auto_increment,
username varchar(100),
role_name varchar(100),
constraint pk_user_roles primary key(id)
) charset=utf8 ENGINE=InnoDB;
create unique index idx_user_roles on user_roles(username, role_name);
create table roles_permissions(
id bigint auto_increment,
role_name varchar(100),
permission varchar(100),
constraint pk_roles_permissions primary key(id)
) charset=utf8 ENGINE=InnoDB;
create unique index idx_roles_permissions on roles_permissions(role_name, permission);
insert into users(username,password)values('zhang','123');配置shiro-jdbc-realm
resource下新建shiro-jdbc-realm.ini
1
2
3
4
5
6
7
8
9jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
dataSource=com.alibaba.druid.pool.DruidDataSource
dataSource.driverClassName=com.mysql.jdbc.Driver
dataSource.url=jdbc:mysql://localhost:3306/shiro
dataSource.username=root
dataSource.password=123456
jdbcRealm.dataSource=$dataSource
securityManager.realms=$jdbcRealmJdbcRealm是shrio提供的。可继承并重写方法来改写sql
junit测试
修改shiro-jdbc-realm.ini
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18@Test
public void testJdbcRealm(){
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-jdbc-realm.ini");
SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("zhang","123");
try {
subject.login(token);
} catch (AuthenticationException e){
// 认证失败
e.printStackTrace();
System.out.println("登录失败");
}
Assert.assertEquals(true, subject.isAuthenticated());// 断言用户已经登录
subject.logout();
}