一、Shiro授权
1.授权,也叫访问控制,即在应用中控制谁访问那些资源(如访问页面/编辑数据/页面操作等)。在授权中需要了解的几个关键对象:主体(Subject),资源(Resource),权限(Permission),角色(Role)。
2.主体(Subject):访问应用的用户,在Shiro中使用Subject代表该用户。用户只有授权后才允许访问相应的资源。
3.资源(Resource):在应用中用户可以访问的url,比如访问jsp页面,查看/编辑某些数据,访问某个业务方法,打印文本等等都是资源。用户只有授权后才能访问。
4.权限(Permission):安全策略中的原子授权单位,通过权限我们可以表示用户在应用中用户有没有操作这个资源的权利。即权限表示在应用中能不能访问某个资源,如:访问用户列表页面查看/新增/修改/删除用户数据(很多时候都是CRUD式权限控制等)。权限代表了用户有没有操作某个资源的权利,即反映在某个资源上的操作允不允许。
5.shiro支持粗粒度权限(如用户模块的所有权限)和细粒度权限(操作某个用户的权限,即实例级别的)
1.授权,也叫访问控制,即在应用中控制谁访问那些资源(如访问页面/编辑数据/页面操作等)。在授权中需要了解的几个关键对象:主体(Subject),资源(Resource),权限(Permission),角色(Role)。
2.主体(Subject):访问应用的用户,在Shiro中使用Subject代表该用户。用户只有授权后才允许访问相应的资源。
3.资源(Resource):在应用中用户可以访问的url,比如访问jsp页面,查看/编辑某些数据,访问某个业务方法,打印文本等等都是资源。用户只有授权后才能访问。
4.权限(Permission):安全策略中的原子授权单位,通过权限我们可以表示用户在应用中用户有没有操作这个资源的权利。即权限表示在应用中能不能访问某个资源,如:访问用户列表页面查看/新增/修改/删除用户数据(很多时候都是CRUD式权限控制等)。权限代表了用户有没有操作某个资源的权利,即反映在某个资源上的操作允不允许。
5.shiro支持粗粒度权限(如用户模块的所有权限)和细粒度权限(操作某个用户的权限,即实例级别的)
6.角色(Role):权限的集合,一般情况下会赋予用户角色而不是权限,即这样的用户可以拥有一组权限,赋予权限时比较方便。典型的如:项目经理,技术总监,CTO,开发工程师等都是角色,不同的角色拥有一组不同的权限。
二、Shiro支持三种授权方式
- 编程式:通过写if/else授权代码块完成
- 注解式:通过在执行的java方法上放置相应的注解完成,没有权限将抛出相应的异常
- jsp/GSP标签:在JSP/GSP页面通过相应的标签完成
三、Shiro授权的Realm编写
1).需要继承自AuthorizingRealm类,并实现doGetAuthorizationInfo方法
2).AuthorizingRealm 类继承自 AuthenticatingRealm ,但没有实现 AuthenticatingRealm 的 doGetAuthenticationInfo 方法。所以认证和授权只需要继承 AuthorizingRealm 就可以了,同时实现他的两个抽象方法。
实例代码:
package cn.com.shiro.realm;
import java.util.HashSet;
import java.util.Set;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
public class ShiroRealm extends AuthorizingRealm {
//用于认证的方法
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("info--> : FirstRealm is lodding");
//1.把 token 转化为 UsernamePasswordToken 对象
UsernamePasswordToken upToken = (UsernamePasswordToken)token;
//2.从 UsernamePasswordToken 中获取用户名 username
String username = upToken.getUsername();
//3.从数据库中查询 username 对应的记录
System.out.println("从数据库中获得username: " + username + " 所对应的用户信息.");
//4.若用户不存在,则可以抛出 UnknownAccountException 异常
if("unknown".equals(username)){
throw new UnknownAccountException("用户不存在!");
}
//5.根据用户情况 ,决定是否抛出其他 AuthenticationException 异常
if("monster".equals(username)){
throw new LockedAccountException("用户被锁定!");
}
//6.根据用户的情况,构建 AuthenticationInfo 对象并返回,通常使用的实现类是 SimpleAuthenticationInfo
//一下信息是从数据库中获取的
//1).principal:认证的实体信息,可以是username,也可以是实体类的对象
Object principal = username;
//2).credentials:数据库中获取的密码
Object credentials = null;//"fc1709d0a95a6be30bc5926fdb7f22f4";
if(username.equals("admin")){
credentials = "038bdaf98f2037b31f1e75b5b4c9b26e";
}else if(username.equals("user")){
credentials = "038bdaf98f2037b31f1e75b5b4c9b26e";
}
//3).realmName:当前realm对象的name, 调用父类对象的 getName()方法即可
String realmName = getName();
//4).盐值
ByteSource credentialsSalt = ByteSource.Util.bytes(username);
SimpleAuthenticationInfo info = null;//new SimpleAuthenticationInfo(principal, credentials, realmName);
info = new SimpleAuthenticationInfo(principal, credentials, credentialsSalt, realmName);
return info;
}
public static void main(String[] args) {
String algorithmName = "MD5";
Object credentials = "123456";
Object salt = ByteSource.Util.bytes("user");
int hashIterations = 1024;
Object result = new SimpleHash(algorithmName, credentials, salt, hashIterations);
System.out.println(result);
}
//用于授权的方法
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("授权 --> doGetAuthorizationInfo...");
//1.从PrincipalCollection中来获取登录用户的信息
Object principal = principals.getPrimaryPrincipal();
//2.利用登录的用户信息来获取当前用户的角色或权限(可能需要查询数据库)
Set<String> roles = new HashSet<>();
roles.add("user");
if(principal.equals("admin")){
roles.add("admin");
}
//3.创建SimpleAuthorizationInfo , 并设置其roles属性
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roles);
//4.返回 SimpleAuthorizationInfo 对象
return info;
}
}