1. 拦截器与过滤器的区别?
2. 关于Shiro细粒度方法级别控制权限的理解:
基本共识: Spring就是一个解剖工厂,任何一个类被注册到IOC容器中,Spring都会通过反射技术
将这个类"肢解",所谓肢解就是会拿到这些东西: 类,属性,方法,以及它们的声明,它们的注解.
这个时候会有不同的对象要向Spring索要这个对象时,Spring会根据注解给予响应的代理;
在Spring提供代理的时候,有两中选择:1.基于这个类的父接口提供代理; 2.基于这个类本身提供
代理, 我们可以通过在Spring配置文件中用一个属性配置来控制 : proxy-target-class="ture"
表示代理目标基于类=true ,这意味着,代理对象是目标类的子类,那么这个代理子类会继承目标
类的注解配置, 相反,如果 proxy-target-class="false" ,这意味着,代理对象是目标类的兄弟,
这个兄弟类对象只会复制目标类的方法,却不会复制目标类的注解;
基于以上共识:我们来分析Shiro的细粒度方法级别权限控制:
depends-on="lifecycleBeanPostProcessor" >
以上连个配置是让 1. Spring 在创建动态
3. 权限系统有三部分:
1.资源的访问权限定义
1. 定义在 org.apache.shiro.spring.web.ShiroFilterFactoryBean 的 filterChainDefinitions属性中
的url级别权限控制;
2. 定义在 方法注解上的细粒度权限控制(方法级别)
3. 使用shiro的自定义标签, 定义在页面标签上的细粒度权限控制(标签级别)
4. 在
2.用户拥有权限绑定
3.用户拥有权限绑定 与 资源访问权限 的匹配;
4. 粗粒度url权限验证流程:
request 请求发出--->web.xml中的DelegatingFilterProxy 代理过滤器过滤到请求----> 交给application.xml 中的
真正的过滤器 ShiroFilterFactoryBean----> 过滤器将请求交给 "安全管理员" securityManager ----->"安管"读取过滤器中
的 "资源与访问权限对应清单" filterChainDefinitions ----->"安管"找到request要访问的资源需要的权限:permission1 ---->
"安管" 调用 "小弟" realm 的 doGetAuthorizationInfo()方法,获得当前用户所持有的权限: permission2 ---->此时:"安管"已经
从过滤器中拿到 1. 要访问的资源需要的权限:permission1 2. 前用户所持有的权限: permission2 ,所以"安管"可以很轻松地将
两个权限做比较,如果匹配,那么就允许用户访问资源,如果不匹配,则拒绝访问该资源,并跳转到没有权限访问的页面;
5. 简单解释一下为啥登录时要通过 subject 来实现登录:
基本共识: shiro的权限控制执行流程: application -----> subject -----> securityManager -----> realm -----> 安全数据;
是这样的,因为我们是用了shiro,所以所有资源的其实是在shiro的"安全管理员" securityManager 的控制之中, 那些"认证访问资源"
即:访问时需要用户是登录状态的,, 如果我们登录时不通过 subject ,这样会导致subject中没有当前用户的信息,也就是说 "安全管理员"
securityManager会认为当前没有已经登录的用户,所以在访问"认证访问资源" 时 securityManager会误判,导致虽然我们登录(认证)了,
但是仍然访问不到"认证访问资源" 这样岂不是很不合理,所以既然你让人家 shiro 的安全管理员 securityManager 来管理你的资源,那么
你登录时也应该让人家知道,所以怎么才能让人家知道呢,就是通过 subject的login()---->securityManager ----->
realm 的doGetAuthenticationInfo() -----> 调用service完成登录(认证)---->返回认证(登录)信息给 securityManager 来判断当前用户
是否登录,记录状态;
6. 细粒度方法级别权限验证流程:
request请求发出----> 调用 save()方法----> Spring 尝试利用 IOC 创建cglib 动态代理对象,却发现目标类 的save()方法上有
shiro注解,然后就利用AOP 在代理类的save方法上加上前置通知: AuthorizationAttributeSourceAdvisor 来读取save()方法上的
shiro注解,并将结果交给"安管"----->securityManager 获得 save()方法访问应具备的权限 -----> 调用realm的doGetAuthorizationInfo()
方法,来获得当前用户所持有的权限, 然后安管自己会对两个权限作对比,判定是否可以访问资源...;
7 . shiro url粗粒度权限控制与方法级别细粒度权限控制对比分析:
粗粒度url权限控制 | 细粒度方法级别权限控制 | |
资源控制者: | securityManager | securityManager |
资源访问所需权限获取来源: | 过滤器 shiroFilter | Spring框架 (IOC和AOP共同作用) |
当前用户访问权限获取来源: | 小弟: realm | 小弟:realm |
权限不足时处理方式: | 过滤器配置相应友好提示页面 | 抛出相应异常给方法调用者 |
8 .关于最近使用struts2 的默认json插件做json转换时遇到懒加载问题处理方式的说明:
基本共识: 1. 默认情况下以类中get方法开头的都会序列化,
2. 我们使用hibernate查询得到的对象数据如果里边有 对多(类中有 toMany)的时候 ,那么会懒加载,在用struts2
的默认json插件做json转换时,json转换器会要求重新到数据库查询懒加载的数据,这个时候session已经在service层
关闭了,所以会报异常, 那么此时我们的处理方式,经过分析发现懒加载的数据不是我们需要转成json的数据,所以就
直接在它的get方法上边加注解: @JSON(serialize=false) 这样在做json转换时,就会忽略该属性,也就不需要到数据库
查询了,也就没有session已经关闭的问题了;
struts2的json插件:
[8.1]如果不想序列化,get方法上注解 @JSON(serialize=false)
[8.2]如果在属性get方法上面加@JSON(name="newName"),则返回的json数据中名称是指定的新名称
[8.3]@JSON(format ="yyyy-MM-dd'T'HH:mm:ss")设置用于格式化输出、解析日期表单域的格式。
[8.4]@JSON(deserialize=true)设置是否反序列化该属性
拓展:
1. Jackson提供了@Jsonignore这个注解,用于在(反)序列化时,忽略bean的某项属性
2. fastjson 给不想被序列化的属性增加增减JSONField(serialize=false)---fastjson特性