Realm:域,Shiro 从从 Realm 获取安全数据(如用户、角色、权限),就是说 SecurityManager 要验证用户身份,那么它需要从 Realm 获取相应的用户进行比较以确定用户身份是否合法;也需要从 Realm 得到用户相应的角色 / 权限进行验证用户是否能进行操作;可以把 Realm 看成 DataSource,即安全数据源。
我们继承 AuthorizingRealm 而不是实现 Realm 接口;推荐使用 AuthorizingRealm,因为: AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token):表示获取身份验证信息;AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals):表示根据用户身份获取授权信息。这种方式的好处是当只需要身份验证时只需要获取身份验证信息而不需要获取授权信息。对于 AuthenticationInfo 和 AuthorizationInfo 请参考其 Javadoc 获取相关接口信息。
继承 AuthorizingRealm示例:
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import springShiro.domain.User; //自己项目内的类
import springShiro.service.UserService; //自己项目内的类
public class UserRealm extends AuthorizingRealm{
@Autowired
private UserService userService;
//获取授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("执行doGetAuthorizationInfo授权方法!");
//获得当前用户
Subject subject=SecurityUtils.getSubject();
User user=(User) subject.getPrincipal();
//给资源授权
SimpleAuthorizationInfo simpleAuthorizationInfo= new SimpleAuthorizationInfo();
simpleAuthorizationInfo.addStringPermission(user.getRole());
System.out.println("执行doGetAuthorizationInfo授权方法完毕!");
return simpleAuthorizationInfo;
}
//身份验证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("执行doGetAuthenticationInfo认证方法!");
UsernamePasswordToken usertoken=(UsernamePasswordToken) token;
User realUser=userService.findone(usertoken.getUsername(), String.copyValueOf(usertoken.getPassword()));
if (realUser==null) {
System.out.println("验证错误,抛出异常!");
return null;
}
System.out.println("执行doGetAuthenticationInfo认证方法完毕!");
//第一个参数userInfo对象对用的用户名,第二个参数,传的是获取的password,第三个参数,盐–用于加密密码对比
return new SimpleAuthenticationInfo(realUser,realUser.getPassword(),"");
}
}
shiro什么时候会进入doGetAuthorizationInfo(PrincipalCollection principals)
1、subject.hasRole(“admin”) 或 subject.isPermitted(“admin”):自己去调用这个是否有什么角色或者是否有什么权限的时候;
2、@RequiresRoles("admin") :在方法上加注解的时候;
3、[@shiro.hasPermission name = "admin"][/@shiro.hasPermission]:在页面上加shiro标签的时候,即进这个页面的时候扫描到有这个标签的时候。
shiro什么时候会进入doGetAuthenticationInfo(AuthenticationToken token)
1. 调用subject.login(userToken)方法的时候
实现Realm接口示例:
public class MyRealm1 implements Realm {
@Override
public String getName() {
return "a"; //realm name 为 “a”
}
//省略supports方法,具体请见源码
@Override
public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
return new SimpleAuthenticationInfo(
"zhang", //身份 字符串类型
"123", //凭据
getName() //Realm Name
);
}
}