A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 shjava 于 2017-10-26 15:23 编辑

域,ShiroRealm获取安全数据(用户,角色,权限)。
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指定的顺序进行身份认证。


4shiro提供的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;






5JdbcRealm的使用:
【演示】:
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();
}
}
















1 个回复

倒序浏览
好贴
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马