0
点赞
收藏
分享

微信扫一扫

shiro重写filter的了解


shiro的了解 (2014-11-06 15:13:14)
标签: 股票 分类: java
shiro学习:
大体功能是认证、授权、加密、会话管理
一、SecurityManager
所有基于web的应用程序都是用 DefaultWebSecurityManager进行管理,它主要提供如下方面的功能

Authentication(认证)
1、web应用FormAuthenticationFilter拦截器

在web应用中认证是通过FormAuthenticationFilter拦截器来实现的
分析对应源代码:
整个拦截器的执行方法是在AdviceFilter.doFilterInternal进行封装
它调用下面三个方法:

boolean continueChain = preHandle(request, response); //是否继续执行后续拦截器链操作

 if (continueChain) {

 executeChain(request, response, chain);//继续执行拦截器后面的操作

 }

 postHandle(request, response);//拦截器执行完后的操作




preHandle调用

onPreHandle(request, response, pathConfig)

 {

 return isAccessAllowed(request, response, mappedValue) || onAccessDenied(request, response, mappedValue);

 }


 isAccessAllowed(request, response, mappedValue)//是否允许访问

 在AuthenticatingFilter.isAccessAllowed中进行了如下实现:

 Subject subject = getSubject(request, response);

 return subject.isAuthenticated() || (!isLoginRequest(request, response) && isPermissive(mappedValue));

 //只要当前用户已经过认证就直接返回true,




如果isAccessAllowed返回false,则系统执行onAccessDenied

FormAuthenticationFilter.onAccessDenied实现对应的方法

 protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {

 if (isLoginRequest(request, response)) //判断请求是否是登录请求

 {

 if (isLoginSubmission(request, response)) //判断请求是否是post方法

 {

 if (log.isTraceEnabled()) {

 log.trace("Login submission detected. Attempting to execute login.");

 }

 return executeLogin(request, response);//执行登录验证

 } else //如果是get方法则会返回true,跳转到登陆页面

 {

 if (log.isTraceEnabled()) {

 log.trace("Login page view.");

 }

 //allow them to see the login page ;)

 return true;

 }

 } 

 //如果访问的是非登录页面,则跳转到登录页面

 else {

 if (log.isTraceEnabled()) {

 log.trace("Attempting to access a path which requires authentication. Forwarding to the " +

 "Authentication url [" + getLoginUrl() + "]");

 }

 saveRequestAndRedirectToLogin(request, response);

 return false;

 }

 }



 //executeLogin执行真正的登录操作

 protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {

 AuthenticationToken token = createToken(request, response); //创建用户的身份、凭证

 if (token == null) {

 String msg = "createToken method implementation returned null. A valid non-null AuthenticationToken " +

 "must be created in order to execute a login attempt.";

 throw new IllegalStateException(msg);

 }

 try {

 Subject subject = getSubject(request, response);

 subject.login(token); //执行shiro的登录操作

 return onLoginSuccess(token, subject, request, response);//登录成功

 } catch (AuthenticationException e) {

 return onLoginFailure(token, e, request, response);//登录失败

 }

 }



在FormAuthenticationFilter中登录成功和登录失败的具体实现

protected boolean onLoginSuccess(AuthenticationToken token, Subject subject,

 ServletRequest request, ServletResponse response) throws Exception {

 issueSuccessRedirect(request, response); //直接重定向到成功页面

 //we handled the success redirect directly, prevent the chain from continuing:

 return false; //不再执行过滤器链后面的操作

 }


 protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e,

 ServletRequest request, ServletResponse response) {

 setFailureAttribute(request, e); //登录失败,设置异常信息继续执行过滤器链后面的操作

 //login failed, let request continue back to the login page:

 return true;

 }





SessionManager(session管理)
DefaultWebSecurityManager-->sessionManager
有下面几种具体的实现
1、ServletContainerSessionManager(默认)
ServletContainerSessionManager使用web容器提供的session进行管理,所以默认使用DefaultWebSecurityManager管理session和直接使用web容器的session
是没有区别的
ServletContainerSessionManager管理的session对象是org.apache.shiro.web.session.HttpServletSession,该对象代理封装了对javax.servlet.http.HttpSession的操作
2、DefaultWebSessionManager
该session管理器默认指定的sessionDAO = new MemorySessionDAO();
它是基于当前内存来进行管理session,没有使用web容器的session;该中方式在集群环境时会出现问题,比如在同一session中访问不同的机器,则可能某些机器存在session值,有些不存在
除非web server配置成ip_hosts
可以通过该sessionManager来实现通过分布式缓存进行多台机器的session共享,可以采用如下配置







CacheManage(缓存管理)
Realm中使用缓存

在Realm中有2个使用缓存的地方
1、认证缓存
首先判断getAuthenticationCache()是否为空,如果未设置则判断authenticationCachingEnabled=true&&cachingEnabled=true如果都为true
则通过设置的cacheManager中取出name=authenticationCacheName的缓存
也就是说要想使用认证缓存,则在Realm中有2种方式设置
一种是通过设置cacheManager
然后设置 authenticationCacheName(认证缓存名)authenticationCachingEnabled=true、cachingEnabled=true
或者直接设置
public void setAuthenticationCache(Cache authenticationCache)

2、授权缓存
首先判断getAuthorizationCache()如果未设置则判断authorizationCachingEnabled=true&&cachingEnabled=true如果都为true
则通过设置的cacheManager中取出name=authorizationCacheName的缓存
也就是说要想使用授权缓存,则在Realm中有2种方式设置
一种是通过设置cacheManager
然后设置 authorizationCacheName(授权缓存名)、authorizationCachingEnabled=true、cachingEnabled=true
或者直接设置
public void setAuthorizationCache(Cache authorizationCache)

上面有很多变量值需要设置,Realm默认情况下
authorizationCachingEnabled=true(是否可授权缓存)
authenticationCachingEnabled=false(是否可认证缓存)
cachingEnabled=true(是否可缓存)
目前认证缓存功能使用不了,当缓存时序列化时对应的对象无法序列化;而且一般也不要使用认证缓存,避免修改密码无法及时生效
授权缓存可以在session期间有效,session过期后重新取授权

SessionManager中使用缓存
在这里使用缓存的目的主要是管理系统session的缓存,比如系统如果想使用memcached来管理session就可以在这里配置

举报

相关推荐

0 条评论