溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

shiro攔截認證的過程是什么

發(fā)布時間:2021-11-30 10:53:07 來源:億速云 閱讀:146 作者:iii 欄目:開發(fā)技術

這篇文章主要介紹“shiro攔截認證的過程是什么”,在日常操作中,相信很多人在shiro攔截認證的過程是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”shiro攔截認證的過程是什么”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

概述

Shiro是apache旗下一個開源安全框架(http://shiro.apache.org/),它將軟件系統(tǒng)的安全認證相關的功能抽取出來,實現(xiàn)用戶身份認證,權限授權、加密、會話管理等功能,組成了一個通用的安全認證框架。使用shiro就可以非??焖俚耐瓿烧J證、授權等功能的開發(fā),降低系統(tǒng)成本。

Shiro框架三大核心對象

shiro攔截認證的過程是什么

說明:

1)Subject :主體對象,負責提交用戶認證和授權信息。

2)SecurityManager:安全管理器,負責認證,授權等業(yè)務實現(xiàn)。(核心)

3)Realm:領域對象,負責從數(shù)據(jù)層獲取業(yè)務數(shù)據(jù)。

shrio 攔截認證全過程

 1.FilterRegistrationBean過濾注冊bean

@Bean
public FilterRegistrationBean shiroFilterRegistration() {
    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(new DelegatingFilterProxy("shiroFilter"));
    //該值缺省為false,表示生命周期由SpringApplicationContext管理,設置為true則表示由ServletContainer管理
    registration.addInitParameter("targetFilterLifecycle", "true");
    registration.setEnabled(true);
    registration.setOrder(Integer.MAX_VALUE - 1);
    registration.addUrlPatterns("/*");
    return registration;
}

設置過濾的bean

2.shiroFilter 實際過濾配置bean

@Bean("shiroFilter")
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
    ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
    shiroFilter.setSecurityManager(securityManager);

    //oauth過濾
    Map<String, Filter> filters = new HashMap<>(10);
    filters.put("oauth3", new Oauth3Filter());
    shiroFilter.setFilters(filters);

    Map<String, String> filterMap = new LinkedHashMap<>();
    filterMap.put("/webjars/**", "anon");
    filterMap.put("/druid/**", "anon");
    filterMap.put("/login", "anon");

    filterMap.put("/**", "oauth3");
    shiroFilter.setFilterChainDefinitionMap(filterMap);

    return shiroFilter;
}

配置oauth3Filter為過濾類 過濾對象處/webjars/** /druid/** /login 外的所有

3.過濾類Oauth3Filter 繼承 AuthenTicationFilter 重寫以下方法

/**
 * 驗證是否有效token
 * @param request re
 * @param response res
 * @return 驗證token
 * @throws Exception
 */
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
    //獲取請求token,如果token不存在,直接返回401
    String token = getRequestToken((HttpServletRequest) request);
    if(StringUtils.isBlank(token)){
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        httpResponse.setContentType("application/json;charset=utf-8");
        httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
        httpResponse.setHeader("Access-Control-Allow-Origin", HttpContextUtils.getOrigin());

        String json = new Gson().toJson(new Result().error(ErrorCode.UNAUTHORIZED));

        httpResponse.getWriter().print(json);

        return false;
    }

    return executeLogin(request, response);
}

4.調(diào)用父類 executeLogin 進行登錄驗證

protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
    AuthenticationToken token = this.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);
    } else {
        try {
            Subject subject = this.getSubject(request, response);
            subject.login(token);
            return this.onLoginSuccess(token, subject, request, response);
        } catch (AuthenticationException var5) {
            return this.onLoginFailure(token, var5, request, response);
        }
    }
}

5.subject.login(token); 進行登錄

login方法被DelegatingSubject重寫

public void login(AuthenticationToken token) throws AuthenticationException {
    **
    Subject subject = this.securityManager.login(this, token);
    **
}

6.securityManager.login(this, token) login被DefaultSecurityManager

接下來幾步?jīng)]那么重要省略部分

7.ModularRealmAuthenticator AuthenticationInfo 授權信息獲取方法

protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {
    this.assertRealmsConfigured();
    Collection<Realm> realms = this.getRealms();
    return realms.size() == 1 ? this.doSingleRealmAuthentication((Realm)realms.iterator().next(), authenticationToken) : this.doMultiRealmAuthentication(realms, authenticationToken);
}

getRealms 獲取我們自己重寫的Realms類,主要用戶獲取用戶信息

8.接下來則進入我們自己寫的Realms類 我的類叫Oauth3Realm

/**
 * 認證(登錄時調(diào)用)
 */
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
    String accessToken = (String) token.getPrincipal();

    //根據(jù)accessToken,查詢用戶信息
    SysUserTokenEntity tokenEntity = shiroService.getByToken(accessToken);
    //token失效
    if(tokenEntity == null || tokenEntity.getExpireDate().getTime() < System.currentTimeMillis()){
        throw new IncorrectCredentialsException(MessageUtils.getMessage(ErrorCode.TOKEN_INVALID));
    }

    //查詢用戶信息
    SysUserEntity userEntity = shiroService.getUser(tokenEntity.getUserId());

    //轉換成UserDetail對象
    UserDetail userDetail = ConvertUtils.sourceToTarget(userEntity, UserDetail.class);

    //獲取用戶對應的部門數(shù)據(jù)權限
    List<Long> deptIdList = shiroService.getDataScopeList(userDetail.getId());
    userDetail.setDeptIdList(deptIdList);

    //賬號鎖定
    if(userDetail.getStatus() == 0){
        throw new LockedAccountException(MessageUtils.getMessage(ErrorCode.ACCOUNT_LOCK));
    }

    SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(userDetail, accessToken, getName());
    return info;
}

負責獲取用戶信息的方法

這并不是登錄的過程,而是授權過濾的過程,通過token到數(shù)據(jù)庫查詢是否有這個用戶,且沒有過期,則證明已經(jīng)登錄。

到此,關于“shiro攔截認證的過程是什么”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續(xù)學習更多相關知識,請繼續(xù)關注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

AI