Realm域​,​​Shiro​​​从​​Realm​​​获取安全数据(如用户、角色、权限),就是说​​SecurityManager​​​要验证用户身份,那么它需要从​​Realm​​​获取相应的用户进行比较以确定用户身份是否合法;也需要从​​Realm​​​得到用户相应的角色/权限进行验证用户是否能进行操作;可以把​​Realm​​​看成​​DataSource​​​,即安全数据源。如我们之前的ini配置方式将使用​​org.apache.shiro.realm.text.IniRealm​​。

org.apache.shiro.realm.Realm接口如下:

String getName(); //返回一个唯一的Realm名字  
boolean supports(AuthenticationToken token); //判断此Realm是否支持此Token
AuthenticationInfo getAuthenticationInfo(AuthenticationToken token)
throws AuthenticationException; //根据Token获取认证信息

单Realm配置

1、自定义Realm实现(com.github.zhangkaitao.shiro.chapter2.realm.MyRealm1):

public class MyRealm1 implements Realm {  
@Override
public String getName() {
return "myrealm1";
}
@Override
public boolean supports(AuthenticationToken token) {
//仅支持UsernamePasswordToken类型的Token
return token instanceof UsernamePasswordToken;
}
@Override
public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String username = (String)token.getPrincipal(); //得到用户名
String password = new String((char[])token.getCredentials()); //得到密码
if(!"zhang".equals(username)) {
throw new UnknownAccountException(); //如果用户名错误
}
if(!"123".equals(password)) {
throw new IncorrectCredentialsException(); //如果密码错误
}
//如果身份认证验证成功,返回一个AuthenticationInfo实现;
return new SimpleAuthenticationInfo(username, password, getName());
}
}

2、ini配置文件指定自定义Realm实现(shiro-realm.ini)

#声明一个realm  
myRealm1=com.github.zhangkaitao.shiro.chapter2.realm.MyRealm1
#指定securityManager的realms实现
securityManager.realms=$myRealm1

通过$name来引入之前的realm定义

3、测试用例请参考com.github.zhangkaitao.shiro.chapter2.LoginLogoutTest的testCustomRealm测试方法,只需要把之前的shiro.ini配置文件改成shiro-realm.ini即可。

多Realm配置

1、ini配置文件(shiro-multi-realm.ini)

#声明一个realm  
myRealm1=com.github.zhangkaitao.shiro.chapter2.realm.MyRealm1
myRealm2=com.github.zhangkaitao.shiro.chapter2.realm.MyRealm2
#指定securityManager的realms实现
securityManager.realms=$myRealm1,$myRealm2

​securityManager​​​会按照​​realms​​​指定的顺序进行身份认证。此处我们使用显示指定顺序的方式指定了​​Realm​​​的顺序,如果删除​​“securityManager.realms=$myRealm1,$myRealm2”​​​,那么​​securityManager​​​会按照​​realm​​​声明的顺序进行使用(即无需设置​​realms​​​属性,其会自动发现),当我们显示指定​​realm​​​后,其他没有指定​​realm​​​将被忽略,如​​“securityManager.realms=$myRealm1”​​​,那么​​myRealm2​​不会被自动设置进去。

2、测试用例请参考com.github.zhangkaitao.shiro.chapter2.LoginLogoutTest的testCustomMultiRealm测试方法。

Shiro默认提供的Realm

05 Shrio Realm_apache

以后一般继承​​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查询相应的信息,如​​“select password from users where username = ?”获取用户密码,“select password, password_salt from users where username = ?”获取用户密码及盐;“select role_name from user_roles where username = ?”获取用户角色;“select permission from roles_permissions where role_name = ?”​​获取角色对应的权限信息;也可以调用相应的api进行自定义sql;

JDBC Realm使用

1、数据库及依赖

<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数据库及druid连接池;

2、到数据库shiro下建三张表:​​users(用户名/密码)​​​、​​user_roles(用户/角色​​​)、​​roles_permissions(角色/权限)​​,具体请参照shiro-example-chapter2/sql/shiro.sql;并添加一个用户记录,用户名/密码为zhang/123;

3、ini配置(shiro-jdbc-realm.ini)

jdbcRealm=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=
jdbcRealm.dataSource=$dataSource
securityManager.realms=$jdbcRealm

1、变量名=全限定类名会自动创建一个类实例

2、变量名.属性=值 自动调用相应的setter方法进行赋值

3、$变量名 引用之前的一个对象实例

4、测试代码请参照com.github.zhangkaitao.shiro.chapter2.LoginLogoutTest的testJDBCRealm方法,和之

前的没什么区别。