shiro 认证filter 的原理

20 篇文章 0 订阅
7 篇文章 0 订阅

正常情况下,如果我们只是简单的用户名,密码登录,则我们做认证 只要配置默认认证过滤器就好了,

如下:

1   配置文件配置登录认证

<bean id="shiroFilter" 
   class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> 
   <property name="securityManager" ref="securityManager"/> 
   <property name="loginUrl" 
      value="http://casserver/login?service=http://casclient/shiro-cas"/> 
   <property name="successUrl" value="/welcome.do"/> 
   <property name="unauthorizedUrl" value="/403.do"/> 
   <property name="filterChainDefinitions"> 
      <value> 
         /logout.do*=anon 
         /casticketerror.do*=anon 
          
         # 权限配置示例
         /security/account/view.do=authc,perms[SECURITY_ACCOUNT_VIEW] 
          
         /** = authc 
      </value> 
   </property> 
 </bean> 

如下配置中没有自己定义shiro 过滤器,所以 都是默认过滤器,比如:

Shiro内置的FilterChain 

Filter NameClass
anonorg.apache.shiro.web.filter.authc.AnonymousFilter
authcorg.apache.shiro.web.filter.authc.FormAuthenticationFilter
authcBasicorg.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter
permsorg.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter
portorg.apache.shiro.web.filter.authz.PortFilter
restorg.apache.shiro.web.filter.authz.HttpMethodPermissionFilter
rolesorg.apache.shiro.web.filter.authz.RolesAuthorizationFilter
sslorg.apache.shiro.web.filter.authz.SslFilter
userorg.apache.shiro.web.filter.authc.UserFilter



当访问对应的url 的时候,会有对应的过滤器 执行过滤,

比如FormAuthenticationFilter  这个类继承了AuthenticatingFilter 抽象类,

抽象类里有一个方法 :

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);
        return onLoginSuccess(token, subject, request, response);
    } catch (AuthenticationException e) {
        return onLoginFailure(token, e, request, response);
    }
}

当 需要FormAuthenticationFilter 这个过滤器进行 认证或者权限过滤时候,就会首先走到这个方法内,创建 token,然后 获取subject 执行login方法,如代码所示,如果 成功了,会执行 FormAuthenticationFilter  类的onloginSuccess 方法,失败执行onLoginFailure 方法。


每次请求一个新的需要认证的 url 的时候,就需要走到这方法,进行过滤。

举例说明 :访问/login 方法 会被进行过滤,onloginSuccess 方法里会再重定向到/login 方法执行。


protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) throws Exception {
       //登录成功后,从session中去除校验码
       Session session = subject.getSession();
       session.removeAttribute(CAPTCHA_SESSION);

       //触发执行鉴权方法
       SecurityManager.isSessionUserAdminRole();
   if (redirectToSavedRequest) {
      return super.onLoginSuccess(token, subject, request, response);
   } else {
      WebUtils.issueRedirect(request, response, getSuccessUrl());
      return false;
   }
}


另一种实现认证方式:

也可以不配置/login =authc 

而是在/login 对应的控制器方法内,创建token 并执行

 Subject subject = getSubject(request, response);
        subject.login(token);
然后在执行 subject.isAuthenticated()进行判断 。
 
 
两种方式都可以实现,但是推荐使用第一种。因为配置简单。没有代码侵入。第二种容易理解。 
subject.login(token); 执行内部逻辑 会走到AuthorizingRealm 进行认证,并返回认证结果。 当然也可以配置多个realm.


授权filter 和认证filter 原理差不多,用RolesAuthorizationFilter 做例子: 
public class RolesAuthorizationFilter extends AuthorizationFilter {

    //TODO - complete JavaDoc

    @SuppressWarnings({"unchecked"})
    public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {

        Subject subject = getSubject(request, response);
        String[] rolesArray = (String[]) mappedValue;

        if (rolesArray == null || rolesArray.length == 0) {
            //no roles specified, so nothing to check - allow access.
            return true;
        }

        Set<String> roles = CollectionUtils.asSet(rolesArray);
        return subject.hasAllRoles(roles);
    }

}



在配置文件中配置了 role[sad] 后,会调用到
isAccessAllowed方法,可以看到 把sad 角色转化进去了,然后判断当前用户是否拥有这个角色。
执行 hasAllRoles 最后会调用
AuthorizingRealm 进行授权判断,并返回授权结果。 当然也可以配置多个realm.
 






  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值