title | category | tag | date |
---|---|---|---|
[Shiro]Shiro架构理解及源码走读 |
Java |
Shiro |
2018-12-12 16:00:00 -0800 |
本项目为简单的shiro入门demo , 其中会涉及本人shiro架构理解,以及简单的源码走读
- 认证(authentication): 你是谁?
- 授权(authorization): 你可以做什么?
- 角色(role)的定义: 开发者自定义的角色 , 如
admin
,vip
,user
- 权限(permission)
shiro结构中的名词:
- Subject : 主体, 需要被验证/发起操作者
- SecurityManager: 安全管理器, 对 Subject 的进行安全操作
- Authenticator : 认证器, 认证Subject身份
- Authorizor: 授权器, 给 Subject 授权
- SessionManager
- CacheManager
- SessionDAO: 管理session数据
- Realm: 数据源, 决定
认证信息
和授权信息
来源
- SecurityManager 是整个框架的核心 , 包含
Authenticator
,Authorizor
,SessionManager
,CacheManager
,Realm
,SessioinDAO
- Realm 提供 Authenticator 的 认证需要的信息源 , 提供 Authorizor 授权信息源
- SessionManager管理session, SessionDAO管理session数据
- 获取用户的token信息
- Subject.login() , 底层是在 realm 中比较信息差异
- 如果登录成功, 返回认证信息
- 获取用户的认证信息
- 获取用户的授权信息
- 检查用户是否有权限
- Permission 定义
/**
* the permission string
* in separate columns (e.g. 'domain', 'actions' and 'targets' columns)
*/
public class DomainPermission extends WildcardPermission {
private String domain;
private Set<String> actions;
private Set<String> targets;
}
public class WildcardPermission implements Permission, Serializable {
protected static final String WILDCARD_TOKEN = "*";
protected static final String PART_DIVIDER_TOKEN = ":";
protected static final String SUBPART_DIVIDER_TOKEN = ",";
protected static final boolean DEFAULT_CASE_SENSITIVE = false;
private List<Set<String>> parts;
public String toString() {
StringBuilder buffer = new StringBuilder();
for (Set<String> part : parts) {
if (buffer.length() > 0) {
buffer.append(PART_DIVIDER_TOKEN);
}
Iterator<String> partIt = part.iterator();
while(partIt.hasNext()) {
buffer.append(partIt.next());
if (partIt.hasNext()) {
buffer.append(SUBPART_DIVIDER_TOKEN);
}
}
}
return buffer.toString();
}
}
看完源码之后才发现定义应该是这样
资源标识 : 动作... : 资源Id...
domain : action1,action2,action3 : target1,target2,target3
domain : * : target1,target2
domain : action1 : *
domain: *
具体匹配算法和流程 org.apache.shiro.authz.permission.WildcardPermission#implies 方法
Realm 是认证信息、授权信息数据来源的组件
简单的 ini
文件 , 按照一定的规则定义 用户, 角色, 权限
[users] #写死的
用户=密码,角色...
[roles] #写死的
角色=权限...
- 继承
org.apache.shiro.realm.AuthorizingRealm
- 重写
doGetAuthenticationInfo
获取认证信息 - 重写
doGetAuthorizationInfo
获取授权信息
在自定义的 ShiroConfig
类中添加:
@Bean
public CustomRealm customRealm() {
return new CustomRealm();
}
@Bean
public WebSecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(customRealm());
return securityManager;
}
-
@RequiresAuthentication
: 表明这个接口的访问需要经过认证//the current Subject to have been authenticated during their current session @Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface RequiresAuthentication { }
-
@RequiresPermissions
@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface RequiresPermissions { String[] value(); // 权限列表 Logical logical() default Logical.AND; //验证权限,满足的逻辑关系, and/or }
@RequiresPermissions(value={"admin","vip"}, logical=Logical.OR) admin/vip 可以访问
-
@RequiresRoles
: 表明接口访问需要角色@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface RequiresRoles { String[] value(); //角色列表 Logical logical() default Logical.AND; //验证角色, 满足的逻辑关系 and/or }
-
@RequiresUser
,@RequiresGuest
: 就是用户和访客的区别
-
maven依赖
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.3.2</version> </dependency>
-
shiro-bean 生命周期管理 , AOP 配置
/** * 管理shiroBean的生命周期 , 这个方法必须是静态的, * 在类加载之前就完成实例化, 否则Spring启动异常, 属性注入异常 */ @Bean public static LifecycleBeanPostProcessor lifecycleBeanPostProcessor() { return new LifecycleBeanPostProcessor(); } /** * 解决 Shiro注解不生效 */ @Bean public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() { DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator(); defaultAdvisorAutoProxyCreator.setProxyTargetClass(true); return defaultAdvisorAutoProxyCreator; } /** * 开启shiro aop支持 */ @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() { AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager()); return authorizationAttributeSourceAdvisor; }
git地址: