本帖最后由 shjava 于 2017-10-26 15:23 编辑
域,Shiro从Realm获取安全数据(用户,角色,权限)。 SecurityManager校验用户身份,会从Ream中获取数据进行比较确定用户身份是否合法。也需要从Realm中获取用户是否有对应用户和权限进行操作。 我们可以把Realm当作数据源。从而获取用户校验和授权功能 Realm接口的代码: [Java] 纯文本查看 复制代码 publicinterface Realm {[/font][font=Simsun, serif]
String getName();// [/font][font=宋体]返回一个唯一的[/font][font=Simsun, serif] Realm [/font][font=宋体]名字[/font][font=Simsun, serif]
booleansupports(AuthenticationToken token);// [/font][font=宋体]判断此[/font][font=Simsun, serif]Realm [/font][font=宋体]是否支持此[/font][font=Simsun, serif] Token[/font][font=Simsun, serif]
AuthenticationInfo getAuthenticationInfo(AuthenticationTokentoken) throws AuthenticationException;// [/font][font=宋体]根据[/font][font=Simsun, serif]Token [/font][font=宋体]获取认证信息[/font][font=Simsun, serif]
}
自定义单Realm的配置: 【演示】: 1、新建maven子项目 [Java] 纯文本查看 复制代码 <dependency>[/font][font=Simsun, serif]
<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;[/font][font=Simsun, serif]
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) {
// [/font][font=宋体]仅支持[/font][font=Simsun, serif]UsernamePasswordToken [/font][font=宋体]类型的[/font][font=Simsun, serif]Token[/font][font=Simsun, serif]
return token instanceof UsernamePasswordToken;
}
@Override
public AuthenticationInfogetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException{
String username = (String) token.getPrincipal();// [/font][font=宋体]得到用户名[/font][font=Simsun, serif]
String password = new String((char[])token.getCredentials()); // [/font][font=宋体]得到密码[/font][font=Simsun, serif]
if (!"zhangsan".equals(username)) {
throw new UnknownAccountException(); // [/font][font=宋体]如果用户名错误[/font][font=Simsun, serif]
}
if (!"123".equals(password)) {
throw new IncorrectCredentialsException(); // [/font][font=宋体]如果密码错误[/font][font=Simsun, serif]
}
// [/font][font=宋体]如果身份认证验证成功,返回一个[/font][font=Simsun, serif]AuthenticationInfo [/font][font=宋体]实现[/font][font=Simsun, serif];[/font][font=Simsun, serif]
return new SimpleAuthenticationInfo(username,password, getName());
}
}
3、配置shiro-realm.ini配置文件 [Java] 纯文本查看 复制代码 #[/font][font=宋体]声明一个[/font][font=Simsun, serif] realm[/font][font=Simsun, serif]
myRealm=cn.oriki.shiro.realm.MyRealm
#[/font][font=宋体]指定[/font][font=Simsun, serif]securityManager [/font][font=宋体]的[/font][font=Simsun, serif]realms [/font][font=宋体]实现[/font][font=Simsun, serif]
securityManager.realms=$myRealm
4、测试 [Java] 纯文本查看 复制代码 packagecn.oriki.shiro.test;[/font][font=Simsun, serif]
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[/font][font=宋体]、获取[/font][font=Simsun, serif]SecurityManager [/font][font=宋体]工厂,此处使用[/font][font=Simsun, serif]Ini [/font][font=宋体]配置文件初始化[/font][font=Simsun, serif] SecurityManager[/font][font=Simsun, serif]
Factory<org.apache.shiro.mgt.SecurityManager>factory = new IniSecurityManagerFactory(
"classpath:shiro-realm.ini");
// 2[/font][font=宋体]、得到[/font][font=Simsun, serif]SecurityManager [/font][font=宋体]实例并绑定给[/font][font=Simsun, serif] SecurityUtils[/font][font=Simsun, serif]
org.apache.shiro.mgt.SecurityManagersecurityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
// 3[/font][font=宋体]、得到[/font][font=Simsun, serif]Subject [/font][font=宋体]及创建用户名[/font][font=Simsun, serif]/[/font][font=宋体]密码身份验证[/font][font=Simsun, serif] Token([/font][font=宋体]即用户身份[/font][font=Simsun, serif]/[/font][font=宋体]凭证[/font][font=Simsun, serif])[/font][font=Simsun, serif]
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = newUsernamePasswordToken("zhangsan", "123");
// 4[/font][font=宋体]、登录,即身份验证[/font][font=Simsun, serif]
try {
subject.login(token);
} catch (AuthenticationException e) {
// [/font][font=宋体]身份验证失败[/font][font=Simsun, serif]
e.printStackTrace();
}
// 5[/font][font=宋体]、断言用户已经登陆[/font][font=Simsun, serif]
Assert.assertEquals(true,subject.isAuthenticated());
// 6[/font][font=宋体]、退出[/font][font=Simsun, serif]
subject.logout();
}
}
3、自定义多Realm的配置: 和单配置的基本一样,但是我们在shiro-realm.ini的配置,多添加一个自定义域 shiro-realm.ini [Java] 纯文本查看 复制代码 #[/font][font=宋体]声明多个[/font][font=Simsun, serif] realm[/font][font=Simsun, serif]
myRealm=cn.oriki.shiro.realm.MyRealm
myRealm2=cn.oriki.shiro.realm.MyRealm2
#[/font][font=宋体]指定[/font][font=Simsun, serif]securityManager [/font][font=宋体]的[/font][font=Simsun, serif]realms [/font][font=宋体]实现[/font][font=Simsun, serif]
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;[/font][font=Simsun, serif]
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>[/font][font=Simsun, serif]
<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] 纯文本查看 复制代码 #[/font][font=宋体]指定使用[/font][font=Simsun, serif]JdbcRealm[/font][font=宋体]域[/font][font=Simsun, serif]
jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
# [/font][font=宋体]配置[/font][font=Simsun, serif]datasource[/font][font=宋体]数据源[/font][font=Simsun, serif]
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
# [/font][font=宋体]为[/font][font=Simsun, serif]JdbcRealm[/font][font=宋体]注入数据源[/font][font=Simsun, serif]
jdbcRealm.dataSource=$dataSource
securityManager.realms=$jdbcRealm
3、测试 [Java] 纯文本查看 复制代码 package cn.oriki.shiro.test;[/font][font=Simsun, serif]
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[/font][font=宋体]、获取[/font][font=Simsun, serif]SecurityManager [/font][font=宋体]工厂,此处使用[/font][font=Simsun, serif]Ini [/font][font=宋体]配置文件初始化[/font][font=Simsun, serif] SecurityManager[/font][font=Simsun, serif]
Factory<org.apache.shiro.mgt.SecurityManager>factory = new IniSecurityManagerFactory(
"classpath:shiro-jdbcRealm.ini");
// 2[/font][font=宋体]、得到[/font][font=Simsun, serif]SecurityManager [/font][font=宋体]实例并绑定给[/font][font=Simsun, serif]SecurityUtils[/font][font=Simsun, serif]
org.apache.shiro.mgt.SecurityManagersecurityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
// 3[/font][font=宋体]、得到[/font][font=Simsun, serif]Subject [/font][font=宋体]及创建用户名[/font][font=Simsun, serif]/[/font][font=宋体]密码身份验证[/font][font=Simsun, serif] Token([/font][font=宋体]即用户身份[/font][font=Simsun, serif]/[/font][font=宋体]凭证[/font][font=Simsun, serif])[/font][font=Simsun, serif]
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = newUsernamePasswordToken("zhangsan", "123");
// 4[/font][font=宋体]、登录,即身份验证[/font][font=Simsun, serif]
try {
subject.login(token);
} catch (AuthenticationException e) {
// [/font][font=宋体]身份验证失败[/font][font=Simsun, serif]
e.printStackTrace();
}
// 5[/font][font=宋体]、断言用户已经登陆[/font][font=Simsun, serif]
Assert.assertEquals(true,subject.isAuthenticated());
// 6[/font][font=宋体]、退出[/font][font=Simsun, serif]
subject.logout();
}
}
|
|