1、首先调用Subject.isPermitted/hasRole接口,其会委托给SecurityManager
2、SecurityManager接着会委托给内部组件Authorizer
3、Authorizer再将其请求委托给我们的Realm去做;Realm才是真正干活的
4、Realm将用户请求的参数封装成权限对象。再从我们重写的doGetAuthorizationInfo方法中获取从数据库中查询到的权限集合
5、Realm将用户传入的权限对象,与从数据库中查出来的权限对象,进行一一对比。如果用户传入的权限对象在从数据库中查出来的权限对象中,则返回true,否则返回false
进行授权操作的前提:用户必须通过认证
public interface SecurityService {
/**
* @Description 查找用户密码
* @param loginName 用户名称
* @return 密码
*/
Map<String,String> findPasswordByLoginName(String loginName);
/**
* @Description 查询角色
* @param loginName 用户名
* @return 角色字符串列表
*/
List<String> findRoleByLoginName(String loginName);
/**
* @Description 查询资源
* @param loginName 用户名
* @return 资源字符串列表
*/
List<String> findPermissionByLoginName(String loginName);
}
public class SecurityServiceImpl implements SecurityService {
@Override
public Map<String,String> findPasswordByLoginName(String loginName) {
return DigestsUtil.entryptPassword("123");
}
@Override
public List<String> findRoleByLoginName(String loginName) {
List<String> list = new ArrayList<>();
list.add("admin");
list.add("dev");
return list;
}
@Override
public List<String> findPermissionByLoginName(String loginName) {
List<String> list = new ArrayList<>();
list.add("order:add");
list.add("order:list");
list.add("order:del");
return list;
}
}
public class DefinitionRealm extends AuthorizingRealm {
public DefinitionRealm() {
//指定密码匹配方式sha1
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher(DigestsUtil.SHA1);
//指定密码迭代次数
hashedCredentialsMatcher.setHashIterations(DigestsUtil.ITERATIONS);
//使用父层方法是匹配方式生效
setCredentialsMatcher(hashedCredentialsMatcher);
}
/**
* @Description 认证方法
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//获取登录名
String loginName = (String) authenticationToken.getPrincipal();
SecurityService securityService = new SecurityServiceImpl();
Map<String, String> map = securityService.findPasswordByLoginName(loginName);
if(map.isEmpty()){
throw new UnknownAccountException("账户不存在");
}
String salt = map.get("salt");
String password = map.get("password");
return new SimpleAuthenticationInfo(loginName,password, ByteSource.Util.bytes(salt),getName());
}
/**
* @Description 鉴权方法
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//拿到用户凭证信息
String loginName = (String) principalCollection.getPrimaryPrincipal();
//从数据库中查询对应的角色和权限
SecurityService securityService = new SecurityServiceImpl();
List<String> roles = securityService.findRoleByLoginName(loginName);
List<String> permissions = securityService.findPermissionByLoginName(loginName);
//构建资源校验对象
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
simpleAuthorizationInfo.addRoles(roles);
simpleAuthorizationInfo.addStringPermissions(permissions);
return simpleAuthorizationInfo;
}
}
public class HelloShiro {
@Test
public void testPermissionRealm(){
Subject subject = shiroLogin();
//打印登录信息
System.out.println("登录结果:"+subject.isAuthenticated());
//-------校验当前用户是否拥有管理员的角色
System.out.println("是否有管理员角色"+subject.hasRole("admin"));
//-------校验当前用户没有的角色
try {
subject.checkRole("coder");
System.out.println("当前用户有coder角色");
}catch (Exception ex){
System.out.println("当前用户没有coder角色");
}
//-------校验当前用户的权限信息
System.out.println("是否有查看订单的权限"+subject.isPermitted("order:list"));
//-------校验当前用户满意的权限
try {
subject.checkPermission("order:update");
System.out.println("当前用户有修改的权限");
}catch (Exception ex){
System.out.println("当前用户没有修改的权限");
}
}
public Subject shiroLogin(){
//导入INI配置创建工厂
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
//工厂构建安全管理器
SecurityManager securityManager = factory.getInstance();
//使用工具生效安全管理器
SecurityUtils.setSecurityManager(securityManager);
//使用工具获得subject主体
Subject subject = SecurityUtils.getSubject();
//构建账户密码
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("jay","123");
//使用subject主体去登录
subject.login(usernamePasswordToken);
return subject;
}
}
登录结果:true
是否有管理员角色true
当前用户没有coder角色
是否有查看订单的权限true
当前用户没有修改的权限