溫馨提示×

溫馨提示×

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

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

Spring Boot+Shiro如何實現(xiàn)一個Http請求的Basic認(rèn)證

發(fā)布時間:2021-06-15 15:16:52 來源:億速云 閱讀:374 作者:小新 欄目:開發(fā)技術(shù)

這篇文章主要介紹了Spring Boot+Shiro如何實現(xiàn)一個Http請求的Basic認(rèn)證,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

Shiro是一個Java的安全框架,可以簡單實現(xiàn)登錄、鑒權(quán)等等的功能。

Basic認(rèn)證是一種較為簡單的HTTP認(rèn)證方式,客戶端通過明文(Base64編碼格式)傳輸用戶名和密碼到服務(wù)端進行認(rèn)證,通常需要配合HTTPS來保證信息傳輸?shù)陌踩?/p>

實踐部分

首先說明一下測試環(huán)境。

王子已經(jīng)有了一套集成好Shiro的Spring Boot框架,這套框架詳細(xì)代碼就不做展示了,我們只來看一下測試用例。

要測試的接口代碼如下:

/**
 * @author liumeng
 */
@RestController
@RequestMapping("/test")
@CrossOrigin
public class TestAppController extends BaseController {
    /**
     * 數(shù)據(jù)匯總
     */
    @GetMapping("/list")
    public AjaxResult test()
    {
        return success("測試接口!");
    }
}

使用Shiro,一定會有Shiro的攔截器配置,這部分代碼如下:

/**
     * Shiro過濾器配置
     */
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager)
    {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        // Shiro的核心安全接口,這個屬性是必須的
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        // 身份認(rèn)證失敗,則跳轉(zhuǎn)到登錄頁面的配置
        shiroFilterFactoryBean.setLoginUrl(loginUrl);
        // 權(quán)限認(rèn)證失敗,則跳轉(zhuǎn)到指定頁面
        shiroFilterFactoryBean.setUnauthorizedUrl(unauthorizedUrl);
        // Shiro連接約束配置,即過濾鏈的定義
        LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        // 對靜態(tài)資源設(shè)置匿名訪問
        filterChainDefinitionMap.put("/favicon.ico**", "anon");
        filterChainDefinitionMap.put("/lr.png**", "anon");
        filterChainDefinitionMap.put("/css/**", "anon");
        filterChainDefinitionMap.put("/docs/**", "anon");
        filterChainDefinitionMap.put("/fonts/**", "anon");
        filterChainDefinitionMap.put("/img/**", "anon");
        filterChainDefinitionMap.put("/ajax/**", "anon");
        filterChainDefinitionMap.put("/js/**", "anon");
        filterChainDefinitionMap.put("/lr/**", "anon");
        filterChainDefinitionMap.put("/captcha/captchaImage**", "anon");
        // 退出 logout地址,shiro去清除session
        filterChainDefinitionMap.put("/logout", "logout");
        // 不需要攔截的訪問
        filterChainDefinitionMap.put("/login", "anon,captchaValidate");
        filterChainDefinitionMap.put("/ssoLogin", "anon");     // 開啟Http的Basic認(rèn)證
        filterChainDefinitionMap.put("/test/**", "authcBasic"); 
        // 注冊相關(guān)
        filterChainDefinitionMap.put("/register", "anon,captchaValidate");

        Map<String, Filter> filters = new LinkedHashMap<String, Filter>();
        filters.put("onlineSession", onlineSessionFilter());
        filters.put("syncOnlineSession", syncOnlineSessionFilter());
        filters.put("captchaValidate", captchaValidateFilter());
        filters.put("kickout", kickoutSessionFilter());
        // 注銷成功,則跳轉(zhuǎn)到指定頁面
        filters.put("logout", logoutFilter());
        shiroFilterFactoryBean.setFilters(filters);

        // 所有請求需要認(rèn)證authcBasic
        filterChainDefinitionMap.put("/**", "user,kickout,onlineSession,syncOnlineSession");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

        return shiroFilterFactoryBean;
    }

這里我們要關(guān)注的是代碼中的

filterChainDefinitionMap.put("/test/**", "authcBasic");
這部分代碼,它指定了我們的測試接口啟動了Http的Basic認(rèn)證,這就是我們的第一步。

做到這里我們可以嘗試的去用瀏覽器訪問一下接口,會發(fā)現(xiàn)如下情況:

Spring Boot+Shiro如何實現(xiàn)一個Http請求的Basic認(rèn)證

這就代表Basic認(rèn)證已經(jīng)成功開啟了,這個時候我們輸入系統(tǒng)的用戶名和密碼,你以為它就能成功訪問了嗎?

答案是否定的,我們只是開啟了認(rèn)證,但并沒有實現(xiàn)認(rèn)證的邏輯。

王子通過閱讀部分Shiro源碼,發(fā)現(xiàn)每次發(fā)送請求后,都會調(diào)用ModularRealmAuthenticator這個類的doAuthenticate方法,源碼如下:

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

可以看出,這個方法主要就是對Realm進行了管理,因為我們的系統(tǒng)本身已經(jīng)有兩個Ream了,針對的是不同情況的權(quán)限驗證,所以為了使用起來不沖突,我們可以繼承這個類來實現(xiàn)我們自己的邏輯,在配置類中增加如下內(nèi)容即可:

@Bean
    public ModularRealmAuthenticator modularRealmAuthenticator(){
        //用自己重新的覆蓋
        UserModularRealmAuthericator modularRealmAuthericator = new UserModularRealmAuthericator();
        modularRealmAuthericator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
        return modularRealmAuthericator;
    }

然后在我們自己的UserModularRealmAuthericator類中重寫doAuthenticate方法就可以了,這里面的具體實現(xiàn)邏輯就要看你們自己的使用場景了。

我們可以自己新創(chuàng)建一個Realm來單獨校驗Basic認(rèn)證的情況,或者共用之前的Realm,這部分就自由發(fā)揮了。

大概內(nèi)容如下:

public class UserModularRealmAuthericator extends ModularRealmAuthenticator {
    private static final Logger logger = LoggerFactory.getLogger(UserModularRealmAuthericator.class);

    @Override
    protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {
        assertRealmsConfigured();
        //強制轉(zhuǎn)換返回的token
        UsernamePasswordToken  usernamePasswordToken = (UsernamePasswordToken) authenticationToken;//所有Realm
        Collection<Realm> realms = getRealms();
        //最終選擇的Realm
        Collection<Realm> typeRealms = new ArrayList<>();
        for(Realm realm:realms){
            if(...){ //這部分是自己的邏輯判斷,過濾出想要使用的Realm
                typeRealms.add(realm);
            }
        }
        //判斷是單Realm 還是多Realm
        if(typeRealms.size()==1){
            return doSingleRealmAuthentication(typeRealms.iterator().next(),usernamePasswordToken);
        }else{
            return doMultiRealmAuthentication(typeRealms,usernamePasswordToken);
        }
    }
}

Realm的具體實現(xiàn)代碼這里就不做演示了,無非就是判斷用戶名密碼是否能通過校驗的邏輯。如果不清楚,可以自行了解Realm的實現(xiàn)方式。

Realm校驗實現(xiàn)后,Basic認(rèn)證就已經(jīng)實現(xiàn)了。

測試部分

接下來我們再次使用瀏覽器對接口進行測試,輸入用戶名和密碼,就會發(fā)現(xiàn)接口成功響應(yīng)了。

我們來抓取一下請求情況

Spring Boot+Shiro如何實現(xiàn)一個Http請求的Basic認(rèn)證

可以發(fā)現(xiàn),Request Header中有了Basic認(rèn)證的信息Authorization: Basic dGVzdDoxMjM0NTY=

這部分內(nèi)容是這樣的,Basic為一個固定的寫法,dGVzdDoxMjM0NTY=這部分內(nèi)容是userName:Password組合后的Base64編碼,所以我們只要給第三方提供這個編碼,他們就可以通過編碼訪問我們的接口了。

使用PostMan測試一下

Spring Boot+Shiro如何實現(xiàn)一個Http請求的Basic認(rèn)證

可以發(fā)現(xiàn)接口是可以成功訪問的。

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“Spring Boot+Shiro如何實現(xiàn)一個Http請求的Basic認(rèn)證”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識等著你來學(xué)習(xí)!

向AI問一下細(xì)節(jié)

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

AI