域,Shiro从Realm获取安全数据(用户,角色,权限)。
SecurityManager校验用户身份,会从Ream中获取数据进行比较确定用户身份是否合法。也需要从Realm中获取用户是否有对应用户和权限进行操作。
我们可以把Realm当作数据源。从而获取用户校验和授权功能
Realm接口的代码:
[Java] 纯文本查看 复制代码
publicinterface Realm {
String getName();// 返回一个唯一的 Realm 名字
booleansupports(AuthenticationToken token);// 判断此Realm 是否支持此 Token
AuthenticationInfo getAuthenticationInfo(AuthenticationTokentoken) throws AuthenticationException;// 根据Token 获取认证信息
}
自定义单Realm的配置:
【演示】:
1、新建maven子项目
[Java] 纯文本查看 复制代码
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</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>
2、创建自定义Realm,实现Realm接口,重写方法
[Java] 纯文本查看 复制代码
packagecn.oriki.shiro.realm;
import org.apache.shiro.authc.AuthenticationException;
importorg.apache.shiro.authc.AuthenticationInfo;
importorg.apache.shiro.authc.AuthenticationToken;
importorg.apache.shiro.authc.IncorrectCredentialsException;
importorg.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
importorg.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.realm.Realm;
public class MyRealm implements Realm {
@Override
public String getName() {
return "myRealm";
}
@Override
public boolean supports(AuthenticationTokentoken) {
// 仅支持UsernamePasswordToken 类型的Token
return token instanceof UsernamePasswordToken;
}
@Override
public AuthenticationInfogetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException{
String username = (String) token.getPrincipal();// 得到用户名
String password = new String((char[])token.getCredentials()); // 得到密码
if (!"zhangsan".equals(username)) {
throw new UnknownAccountException(); // 如果用户名错误
}
if (!"123".equals(password)) {
throw new IncorrectCredentialsException(); // 如果密码错误
}
// 如果身份认证验证成功,返回一个AuthenticationInfo 实现;
return new SimpleAuthenticationInfo(username,password, getName());
}
}
3、配置shiro-realm.ini配置文件
[Java] 纯文本查看 复制代码
#声明一个 realm
myRealm=cn.oriki.shiro.realm.MyRealm
#指定securityManager 的realms 实现
securityManager.realms=$myRealm
4、测试
[Java] 纯文本查看 复制代码
packagecn.oriki.shiro.test;
import org.apache.shiro.SecurityUtils;
importorg.apache.shiro.authc.AuthenticationException;
importorg.apache.shiro.authc.UsernamePasswordToken;
importorg.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.junit.Test;
import junit.framework.Assert;
public class ShiroTest {
@Test
public void testHelloworld() {
// 1、获取SecurityManager 工厂,此处使用Ini 配置文件初始化 SecurityManager
Factory<org.apache.shiro.mgt.SecurityManager>factory = new IniSecurityManagerFactory(
"classpath:shiro-realm.ini");
// 2、得到SecurityManager 实例并绑定给 SecurityUtils
org.apache.shiro.mgt.SecurityManagersecurityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
// 3、得到Subject 及创建用户名/密码身份验证 Token(即用户身份/凭证)
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = newUsernamePasswordToken("zhangsan", "123");
// 4、登录,即身份验证
try {
subject.login(token);
} catch (AuthenticationException e) {
// 身份验证失败
e.printStackTrace();
}
// 5、断言用户已经登陆
Assert.assertEquals(true,subject.isAuthenticated());
// 6、退出
subject.logout();
}
}
3、自定义多Realm的配置:
和单配置的基本一样,但是我们在shiro-realm.ini的配置,多添加一个自定义域
shiro-realm.ini
[Java] 纯文本查看 复制代码
#声明多个 realm
myRealm=cn.oriki.shiro.realm.MyRealm
myRealm2=cn.oriki.shiro.realm.MyRealm2
#指定securityManager 的realms 实现
securityManager.realms=$myRealm,$myRealm2
securityManager会按照realms指定的顺序进行身份认证。
4、shiro提供的Realm:
file:///C:/Users/yst/AppData/Local/Temp/msohtmlclip1/01/clip_image001.png
以后一般继承 AuthorizingRealm(授权)即可;其继承了AuthenticatingRealm(即身份验证),而且也间接继承了CachingRealm(带有缓存实现)。其中主要默认实现如下:
org.apache.shiro.realm.text.IniRealm:[users]部分指定用户名/密码及其角色;[roles]部分指定角色即权限信息;
org.apache.shiro.realm.text.PropertiesRealm:user.username=password,role1,role2指定用户 名/密码及其角色;role.role1=permission1,permission2 指定角色及权限信息;
org.apache.shiro.realm.jdbc.JdbcRealm:通过sql查询相应的信息,如“selectpasswordfrom users where username = ?”获取用户密码,“select password, password_saltfrom userswhere username = ?”获取用户密码及盐;“select role_name from user_roleswhereusername = ?” 获取用户角色;“select permission from roles_permissionswhere role_name= ?”获取角色对应的权限信息;也可以调用相应的api进行自定义sql;
5、JdbcRealm的使用:
【演示】:
0、创建数据库
[SQL] 纯文本查看 复制代码
dropdatabase if exists db_shiro;
create database db_shiro;
use db_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 onusers(username);
create table user_roles(
id bigint auto_increment,
username varchar(100),
role_name varchar(100),
constraint pk_user_roles primarykey(id)
) charset=utf8 ENGINE=InnoDB;
create unique index idx_user_roles onuser_roles(username, role_name);
create table roles_permissions(
id bigint auto_increment,
role_name varchar(100),
permission varchar(100),
constraint pk_roles_permissionsprimary key(id)
) charset=utf8 ENGINE=InnoDB;
create unique index idx_roles_permissions onroles_permissions(role_name, permission);
insert into users(username,password)values('zhangsan','123');
1、新建maven工程,引入依赖
[Java] 纯文本查看 复制代码
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</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>
<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>
2、创建shiro-jdbcRealm.ini,编写配置
[Java] 纯文本查看 复制代码
#指定使用JdbcRealm域
jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
# 配置datasource数据源
dataSource=com.alibaba.druid.pool.DruidDataSource
dataSource.driverClassName=com.mysql.jdbc.Driver
dataSource.url=jdbc:mysql://localhost:3306/db_shiro
dataSource.username=root
dataSource.password=4869
# 为JdbcRealm注入数据源
jdbcRealm.dataSource=$dataSource
securityManager.realms=$jdbcRealm
3、测试
[Java] 纯文本查看 复制代码
package cn.oriki.shiro.test;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
importorg.apache.shiro.authc.UsernamePasswordToken;
importorg.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.junit.Assert;
import org.junit.Test;
public class ShiroTest {
@Test
public void testHelloworld() {
// 1、获取SecurityManager 工厂,此处使用Ini 配置文件初始化 SecurityManager
Factory<org.apache.shiro.mgt.SecurityManager>factory = new IniSecurityManagerFactory(
"classpath:shiro-jdbcRealm.ini");
// 2、得到SecurityManager 实例并绑定给SecurityUtils
org.apache.shiro.mgt.SecurityManagersecurityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
// 3、得到Subject 及创建用户名/密码身份验证 Token(即用户身份/凭证)
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = newUsernamePasswordToken("zhangsan", "123");
// 4、登录,即身份验证
try {
subject.login(token);
} catch (AuthenticationException e) {
// 身份验证失败
e.printStackTrace();
}
// 5、断言用户已经登陆
Assert.assertEquals(true,subject.isAuthenticated());
// 6、退出
subject.logout();
}
}