Shiro-BasicHttpAuthenticationFilter 鉴权过滤器的使用方式

它的作用是用来根据路径匹配结果,调用相应过滤器

onPreHandle

这里是正在的执行逻辑,之前的都是判断,它返回了两个方法:

  • isAccessAllowed()
  • onAccessDenied()

​ 这两个方法通过||运算符连接,其实有一个逻辑判断过程【先判断isAccessAllowed:访问是否允许,如果允许则通过,如果不允许则进行onAccessDenied:访问拒绝处理的逻辑】。

isAccessAllowed

private boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        Subject subject = getSubject(request, response);
    	//获取Subject,然后调用isAuthenticated()判断是否已经认证过了
        return subject.isAuthenticated();
}

​ 如果上面isAuthenticated为false,那么需要继续判断是否是!isLoginRequest()非登录请求,且isPermissive()是放行的,也就是说判断是否是匿名访问路径。

onAccessDenied

private boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
    boolean loggedIn = false; // false by default or we wouldn't be in this method
    if (isLoginAttempt(request, response)) {
        loggedIn = executeLogin(request, response);
    }
    if (!loggedIn) {
        sendChallenge(request, response);
    }
    return loggedIn;
}

该方法就是isAccessAllowed返回false之后执行的,即访问拒绝的逻辑

​ isLoginAttempt(),该方法前面已经出现,通过请求头判断是否为尝试登陆,如果 true,则执行登录逻辑;反之,sendChallenge

executeLogin

​ BasicHttpAuthenticationFilter 是没有实现 executeLogin() 的,因此将调用父类 AuthenticatingFilter 的 executeLogin() 方法。

private 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);
    }
}

private AuthenticationToken createToken(ServletRequest request, ServletResponse response) {
    String authorizationHeader = getAuthzHeader(request);
    if (authorizationHeader == null || authorizationHeader.length() == 0) {
        // 由于没有授权标头,请创建空的身份验证令牌。
        return createToken("", "", request, response);
    }
 
    log.debug("Attempting to execute login with auth header");
 
    String[] prinCred = getPrincipalsAndCredentials(authorizationHeader, request);
    if (prinCred == null || prinCred.length < 2) {
        // 创建一个密码为空的身份验证令牌,因为请求中没有提供。
        String username = prinCred == null || prinCred.length == 0 ? "" : prinCred[0];
        return createToken(username, "", request, response);
    }
 
    String username = prinCred[0];
    String password = prinCred[1];
 
    return createToken(username, password, request, response);
}

​ 在 createToken 之后,会使用getSubject执行login()。后面会执行securityManager的login方法,在securityManager中会对 token进行验证,本质上就是调用Realm方法验证,如果验证过程中没有异常抛出,则顺利执行。

posted @ 2022-08-09 00:33  MineLSG  阅读(2379)  评论(0编辑  收藏  举报