为什么要自定义Realm
我们之前通过配置文件去获取用户角色权限的信息,但是有些时候希望从数据库中读取权限信息,此时就需要用到自定义Realm。
创建实体类
public class User {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User [username=" + username + ", password=" + password + "]";
}
}
创建自定义的UserRealm
CachingRealm:带有缓存实现
AuthenticatingRealm:认证Realm
AuthorizingRealm:授权Realm
一般我们直接继承AuthorizingRealm,因为它继承了AuthenticatingRealm,
继承AuthorizingRealm可以同时实现认证和授权功能。
public class UserRealm extends AuthorizingRealm{
/**
*授权
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("----进入授权----");
//获取凭证 用户名
String username = (String)principals.getPrimaryPrincipal();
System.out.println("username:" + username);
if (username == null) {
return null;
}
//模拟权限,手动添加
List<String> priList = new ArrayList<String>();
//权限列表
priList.add("user:add");
priList.add("user:query");
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//添加角色
info.addRole("role1");
for (String string : priList) {
//添加权限
info.addStringPermission(string);
System.out.println("----添加权限---- " + string);
}
System.out.println("----授权完成---- ");
return info;
}
/**
* 认证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("----进入认证----");
//获取用户输入的用户名称
String username = token.getPrincipal().toString();
System.out.println("username:" + username);
//获取密码 从数据库查询得到,这里直接获取
String password = "123456";
//将获取到的信息进行封装,第一个参数:身份,第二个参数:证明,第3个参数是当前类名
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, password, this.getName());
System.out.println("----认证完成----");
return info;
}
}
测试UserRealm
public class UserRealmTest {
@Test
public void test1() {
// 创建安全管理器的工厂对象
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
// 通过工厂获取安全管理器对象
SecurityManager securityManager = factory.getInstance();
System.out.println(securityManager.getClass().getSimpleName());
//创建UserRealm
UserRealm userRealm =new UserRealm();
//给SecurityManager注入UserRealm,也可在ini文件中配置
((RealmSecurityManager) securityManager).setRealm(userRealm);
// 将安全管理器绑定到当前线程
SecurityUtils.setSecurityManager(securityManager);
// 使用SecurityUtils得到当前主体对象
Subject subject = SecurityUtils.getSubject();
// 封装用户验证信息
AuthenticationToken token = new UsernamePasswordToken("张三", "123456");
// 认证
try {
subject.login(token);
System.out.println("登陆成功");
System.out.println("是否拥有role1: " +subject.hasRole("role1"));
System.out.println("是否拥有role2: " +subject.hasRole("role2"));
//判断是否具有某些权限
System.out.println("是否拥有权限user:add" + subject.isPermitted("user:add"));
System.out.println("是否拥有权限user:query" + subject.isPermitted("user:query"));
System.out.println("是否拥有权限user:delete" + subject.isPermitted("user:delete"));
} catch (Exception e) {
e.printStackTrace();
System.out.println("用户名或密码不正确");
}
}
}
这里面使用代码注入自定义的Realm,如果使用配置文件的话
注释掉UserRealmTest类的以下两行
//创建UserRealm
UserRealm userRealm =new UserRealm();
//给SecurityManager注入UserRealm,也可在ini文件中配置
((RealmSecurityManager) securityManager).setRealm(userRealm);
新建shiro.ini配置文件
输入以下内容,UserRealm的全限定类名需要按照自己的来写。
[main]
#配置自定义Realm
UserRealm=com.sks.realm.UserRealm
#注入自定义的Realm
securityManager.realm=$UserRealm
类名=全限定类名:会自动创建一个类实例
变量名.属性=值:会自动调用相应的setter方法进行赋值
$变量名:引用之前的一个对象实例