久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

認(rèn)證鑒權(quán)與API權(quán)限控制在微服務(wù)架構(gòu)中的設(shè)計(jì)與實(shí)現(xiàn)(三)

 feimishiwo 2018-08-13

640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1


引言: 本文系《認(rèn)證鑒權(quán)與API權(quán)限控制在微服務(wù)架構(gòu)中的設(shè)計(jì)與實(shí)現(xiàn)》系列的第三篇,,本文重點(diǎn)講解token以及API級(jí)別的鑒權(quán)。本文對(duì)涉及到的大部分代碼進(jìn)行了分析,,歡迎訂閱本系列文章,。


1. 前文回顧

640?wx_fmt=png&wxfrom=5&wx_lazy=1


在開始講解這一篇文章之前,,先對(duì)之前兩篇文章進(jìn)行回憶下。在第一篇《認(rèn)證鑒權(quán)與API權(quán)限控制在微服務(wù)架構(gòu)中的設(shè)計(jì)與實(shí)現(xiàn)(一)》介紹了該項(xiàng)目的背景以及技術(shù)調(diào)研與最后選型,。第二篇《認(rèn)證鑒權(quán)與API權(quán)限控制在微服務(wù)架構(gòu)中的設(shè)計(jì)與實(shí)現(xiàn)(二)》畫出了簡(jiǎn)要的登錄和校驗(yàn)的流程圖,,并重點(diǎn)講解了用戶身份的認(rèn)證與token發(fā)放的具體實(shí)現(xiàn)。


640?wx_fmt=png&wxfrom=5&wx_lazy=1


本文重點(diǎn)講解鑒權(quán),,包括兩個(gè)方面:token合法性以及API級(jí)別的操作權(quán)限,。首先token合法性很容易理解,第二篇文章講解了獲取授權(quán)token的一系列流程,,token是否是認(rèn)證服務(wù)器頒發(fā)的,,必然是需要驗(yàn)證的。其次對(duì)于API級(jí)別的操作權(quán)限,,將上下文信息不具備操作權(quán)限的請(qǐng)求直接拒絕,,當(dāng)然此處是設(shè)計(jì)token合法性校驗(yàn)在先,其次再對(duì)操作權(quán)限進(jìn)行驗(yàn)證,,如果前一個(gè)驗(yàn)證直接拒絕,,通過則進(jìn)入操作權(quán)限驗(yàn)證。


2.資源服務(wù)器配置

640?wx_fmt=png


ResourceServer配置在第一篇就列出了,,在進(jìn)入鑒權(quán)之前,,把這邊的配置搞清,即使有些配置在本項(xiàng)目中沒有用到,,大家在自己的項(xiàng)目有可能用到,。


  1. @Configuration@EnableResourceServerpublic class ResourceServerConfig extends ResourceServerConfigurerAdapter {    //http安全配置
  2.    @Override
  3.    public void configure(HttpSecurity http) throws Exception {        //禁掉csrf,設(shè)置session策略
  4.        http.csrf().disable()
  5.                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
  6.                .and()//默認(rèn)允許訪問
  7.                .requestMatchers().antMatchers("/**")
  8.                .and().authorizeRequests()
  9.                .antMatchers("/**").permitAll()
  10.                .anyRequest().authenticated()
  11.                .and().logout() //logout注銷端點(diǎn)配置
  12.                .logoutUrl("/logout")
  13.                .clearAuthentication(true)
  14.                .logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler())
  15.                .addLogoutHandler(customLogoutHandler());
  16.    }    //添加自定義的CustomLogoutHandler
  17.    @Bean
  18.    public CustomLogoutHandler customLogoutHandler() {        return new CustomLogoutHandler();
  19.    }    //資源安全配置相關(guān)
  20.    @Override
  21.    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {        super.configure(resources);
  22.    }
  23. }


@EnableResourceServer這個(gè)注解很重要,,OAuth2資源服務(wù)器的簡(jiǎn)便注解,。其使得Spring Security filter通過請(qǐng)求中的OAuth2 token來驗(yàn)證請(qǐng)求。通常與EnableWebSecurity配合使用,,該注解還創(chuàng)建了硬編碼的@Order(3) WebSecurityConfigurerAdapter,由于當(dāng)前spring的技術(shù),,order的順序不易修改,,所以在項(xiàng)目中避免還有其他order=3的配置。


關(guān)聯(lián)的HttpSecurity,,與之前的 Spring Security XML中的 "http"元素配置類似,,它允許配置基于web安全以針對(duì)特定http請(qǐng)求。默認(rèn)是應(yīng)用到所有的請(qǐng)求,,通過requestMatcher可以限定具體URL范圍,。HttpSecurity類圖如下。


0?wx_fmt=png


總的來說:HttpSecurity是SecurityBuilder接口的一個(gè)實(shí)現(xiàn)類,,從名字上我們就可以看出這是一個(gè)HTTP安全相關(guān)的構(gòu)建器,。當(dāng)然我們?cè)跇?gòu)建的時(shí)候可能需要一些配置,,當(dāng)我們調(diào)用HttpSecurity對(duì)象的方法時(shí),實(shí)際上就是在進(jìn)行配置,。


authorizeRequests(),,formLogin()、httpBasic()這三個(gè)方法返回的分別是ExpressionUrlAuthorizationConfigurer,、FormLoginConfigurer,、HttpBasicConfigurer,他們都是SecurityConfigurer接口的實(shí)現(xiàn)類,,分別代表的是不同類型的安全配置器,。 


因此,從總的流程上來說,,當(dāng)我們?cè)谶M(jìn)行配置的時(shí)候,,需要一個(gè)安全構(gòu)建器SecurityBuilder(例如我們這里的HttpSecurity),SecurityBuilder實(shí)例的創(chuàng)建需要有若干安全配置器SecurityConfigurer實(shí)例的配合,。


關(guān)聯(lián)的ResourceServerSecurityConfigurer,,為資源服務(wù)器添加特殊的配置,默認(rèn)的適用于很多應(yīng)用,,但是這邊的修改至少以resourceId為單位,。類圖如下。


0?wx_fmt=png


ResourceServerSecurityConfigurer創(chuàng)建了OAuth2核心過濾器OAuth2AuthenticationProcessingFilter,,并為其提供固定了OAuth2AuthenticationManager,。只有被OAuth2AuthenticationProcessingFilter攔截到的oauth2相關(guān)請(qǐng)求才被特殊的身份認(rèn)證器處理。同時(shí)設(shè)置了TokenExtractor,、異常處理實(shí)現(xiàn),。


OAuth2AuthenticationProcessingFilter是OAuth2保護(hù)資源的預(yù)先認(rèn)證過濾器。配合OAuth2AuthenticationManager使用,,根據(jù)請(qǐng)求獲取到OAuth2 token,,之后就會(huì)使用OAuth2Authentication來填充Spring Security上下文。 


OAuth2AuthenticationManager在前面的文章給出的AuthenticationManager類圖就出現(xiàn)了,,與token認(rèn)證相關(guān),。這邊略過貼出源碼進(jìn)行講解,讀者可以自行閱讀,。


3. 鑒權(quán)endpoint

640?wx_fmt=png


鑒權(quán)主要是使用內(nèi)置的endpoint /oauth/check_token,,筆者將對(duì)端點(diǎn)的分析放在前面,因?yàn)檫@是鑒權(quán)的唯一入口,。下面我們來看下該API接口中的主要代碼,。


  1.    @RequestMapping(value = "/oauth/check_token")    @ResponseBody
  2.    public Map<String, ?> checkToken(CheckTokenEntity checkTokenEntity) {        //CheckTokenEntity為自定義的dto
  3.        Assert.notNull(checkTokenEntity, "invalid token entity!");        //識(shí)別token
  4.        OAuth2AccessToken token = resourceServerTokenServices.readAccessToken(checkTokenEntity.getToken());        //判斷token是否為空
  5.        if (token == null) {            throw new InvalidTokenException("Token was not recognised");
  6.        }        //未過期
  7.        if (token.isExpired()) {            throw new InvalidTokenException("Token has expired");
  8.        }        //加載OAuth2Authentication
  9.        OAuth2Authentication authentication = resourceServerTokenServices.loadAuthentication(token.getValue());        //獲取response,token合法性驗(yàn)證完畢
  10.        Map<String, Object> response = (Map<String, Object>) accessTokenConverter.convertAccessToken(token, authentication);        //check for api permission
  11.        if (response.containsKey("jti")) {            //上下文操作權(quán)限校驗(yàn)
  12.            Assert.isTrue(checkPermissions.checkPermission(checkTokenEntity));
  13.        }
  14.        response.put("active", true);    // Always true if token exists and not expired
  15.        return response;
  16.    }


看過security-oauth源碼的同學(xué)可能立馬就看出上述代碼與源碼不同,熟悉/oauth/check_token校驗(yàn)流程的也會(huì)看出來,,這邊筆者對(duì)security-oauth jar進(jìn)行了重新編譯,,修改了部分源碼用于該項(xiàng)目需求的場(chǎng)景。主要是加入了前置的API級(jí)別的權(quán)限校驗(yàn),。


4. token 合法性驗(yàn)證

640?wx_fmt=png


從上面的CheckTokenEndpoint中可以看出,,對(duì)于token合法性驗(yàn)證首先是識(shí)別請(qǐng)求體中的token。用到的主要方法是ResourceServerTokenServices提供的readAccessToken()方法,。該接口的實(shí)現(xiàn)類為DefaultTokenServices,,在之前的配置中有講過這邊配置了jdbc的TokenStore。


  1. public class JdbcTokenStore implements TokenStore {
  2.    ...    public OAuth2AccessToken readAccessToken(String tokenValue) {
  3.        OAuth2AccessToken accessToken = null;        try {            //使用selectAccessTokenSql語句,,調(diào)用了私有的extractTokenKey()方法
  4.            accessToken = jdbcTemplate.queryForObject(selectAccessTokenSql, new RowMapper<OAuth2AccessToken>() {                public OAuth2AccessToken mapRow(ResultSet rs, int rowNum) throws SQLException {                    return deserializeAccessToken(rs.getBytes(2));
  5.                }
  6.            }, extractTokenKey(tokenValue));
  7.        }        //異常情況
  8.        catch (EmptyResultDataAccessException e) {            if (LOG.isInfoEnabled()) {
  9.                LOG.info("Failed to find access token for token " + tokenValue);
  10.            }
  11.        }        catch (IllegalArgumentException e) {
  12.            LOG.warn("Failed to deserialize access token for " + tokenValue, e);            //不合法則移除
  13.            removeAccessToken(tokenValue);
  14.        }        return accessToken;
  15.    }
  16.    ...    //提取TokenKey方法
  17.    protected String extractTokenKey(String value) {        if (value == null) {            return null;
  18.        }
  19.        MessageDigest digest;        try {            //MD5
  20.            digest = MessageDigest.getInstance("MD5");
  21.        }        catch (NoSuchAlgorithmException e) {            throw new IllegalStateException("MD5 algorithm not available.  Fatal (should be in the JDK).");
  22.        }        try {            byte[] bytes = digest.digest(value.getBytes("UTF-8"));            return String.format("%032x", new BigInteger(1, bytes));
  23.        }        catch (UnsupportedEncodingException e) {            throw new IllegalStateException("UTF-8 encoding not available.  Fatal (should be in the JDK).");
  24.        }
  25.    }
  26. }


readAccessToken()檢索出該token值的完整信息,。上述代碼比較簡(jiǎn)單,涉及到的邏輯也不復(fù)雜,,此處簡(jiǎn)單講解,。下圖為debug token校驗(yàn)的變量信息,讀者可以自己動(dòng)手操作下,,截圖僅供參考,。


0?wx_fmt=png


至于后面的步驟,loadAuthentication()為特定的access token 加載credentials,。得到的credentials 與token作為convertAccessToken()參數(shù),,得到校驗(yàn)token的response。


5. API級(jí)別權(quán)限校驗(yàn)

640?wx_fmt=png


筆者項(xiàng)目目前都是基于Web的權(quán)限驗(yàn)證,,之前遺留的一個(gè)巨大的單體應(yīng)用系統(tǒng)正在逐漸拆分,,然而當(dāng)前又不能完全拆分完善。為了同時(shí)兼容新舊服務(wù),,盡量減少對(duì)業(yè)務(wù)系統(tǒng)的入侵,,實(shí)現(xiàn)微服務(wù)的統(tǒng)一性和獨(dú)立性。筆者根據(jù)業(yè)務(wù)業(yè)務(wù)場(chǎng)景,,嘗試在Auth處做操作權(quán)限校驗(yàn),。


首先想到的是資源服務(wù)器配置ResourceServer,如:


http.authorizeRequests()
.antMatchers("/order/**").access("#oauth2.hasScope('select') and hasRole('ROLE_USER')")


這樣做需要將每個(gè)操作接口的API權(quán)限控制放在各個(gè)不同的業(yè)務(wù)服務(wù),,每個(gè)服務(wù)在接收到請(qǐng)求后,,需要先從Auth服務(wù)取出該token 對(duì)應(yīng)的role和scope等權(quán)限信息。這個(gè)方法肯定是可行的,,但是由于項(xiàng)目鑒權(quán)的粒度更細(xì),而且暫時(shí)不想大動(dòng)原有系統(tǒng),,在加上之前網(wǎng)關(guān)設(shè)計(jì),,網(wǎng)關(guān)調(diào)用Auth服務(wù)校驗(yàn)token合法性,所以最后決定在Auth系統(tǒng)調(diào)用中,把這些校驗(yàn)一起解決完,。


文章開頭資源服務(wù)器的配置代碼可以看出,,對(duì)于所有的資源并沒有做攔截,因?yàn)榫W(wǎng)關(guān)處是調(diào)用Auth系統(tǒng)的相關(guān)endpoint,,并不是所有的請(qǐng)求url都會(huì)經(jīng)過一遍Auth系統(tǒng),,所以對(duì)于所有的資源,在Auth系統(tǒng)中,,定義需要鑒權(quán)接口所需要的API權(quán)限,,然后根據(jù)上下文進(jìn)行匹配。這是采用的第二種方式,,也是筆者目前采用的方法,。當(dāng)然這種方式的弊端也很明顯,一旦并發(fā)量大,,網(wǎng)關(guān)還要耗時(shí)在調(diào)用Auth系統(tǒng)的鑒權(quán)上,,TPS勢(shì)必要下降很多,對(duì)于一些不需要鑒權(quán)的服務(wù)接口也會(huì)引起不可用,。另外一點(diǎn)是,,對(duì)于某些特殊權(quán)限的接口,需要的上下文信息很多,,可能并不能完全覆蓋,,對(duì)于此,筆者的解決是分兩方面:一是盡量將這些特殊情況進(jìn)行分類,,某一類的情況統(tǒng)一解決,;二是將嚴(yán)苛的校驗(yàn)降低,對(duì)于上下文校驗(yàn)失敗的直接拒絕,,而通過的,,對(duì)于某些接口,在接口內(nèi)進(jìn)行操作之前,,對(duì)特殊的地方還要再次進(jìn)行校驗(yàn),。


上面在講endpoint有提到這邊對(duì)源碼進(jìn)行了改寫。CheckTokenEntity是自定義的DTO,,這這個(gè)類中定義了鑒權(quán)需要的上下文,,這里是指能校驗(yàn)操作權(quán)限的最小集合,如URI,、roleId,、affairId等等。另外定義了CheckPermissions接口,,其方法checkPermission(CheckTokenEntity checkTokenEntity)返回了check的結(jié)果,。而其具體實(shí)現(xiàn)類則定義在Auth系統(tǒng)中。筆者項(xiàng)目中調(diào)用的實(shí)例如下:


  1. @Componentpublic class CustomCheckPermission implements CheckPermissions {    @Autowired
  2.    private PermissionService permissionService;    @Override
  3.    public boolean checkPermission(CheckTokenEntity checkTokenEntity) {
  4.        String url = checkTokenEntity.getUri();
  5.        Long affairId = checkTokenEntity.getAffairId();
  6.        Long roleId = checkTokenEntity.getRoleId();        //校驗(yàn)
  7.        if (StringUtils.isEmpty(url) || affairId <= 0 || roleId <= 0) {            return true;
  8.        } else {            return permissionService.checkPermission(url, affairId, roleId);
  9.        }
  10.    }
  11. }


關(guān)于jar包spring-cloud-starter-oauth2中的具體修改內(nèi)容,大家可以看下文末筆者的GitHub項(xiàng)目,。通過自定義CustomCheckPermission,,覆寫checkPermission()方法,大家也可以對(duì)自己業(yè)務(wù)的操作權(quán)限進(jìn)行校驗(yàn),,非常靈活,。這邊涉及到具體業(yè)務(wù),筆者在項(xiàng)目中只提供接口,,具體的實(shí)現(xiàn)需要讀者自行完成,。


6. 總結(jié)

640?wx_fmt=png


本文相對(duì)來說比較簡(jiǎn)單,主要講解了token以及API級(jí)別的鑒權(quán),。token的合法性認(rèn)證很常規(guī),,Auth系統(tǒng)對(duì)于API級(jí)別的鑒權(quán)是結(jié)合自身業(yè)務(wù)需要和現(xiàn)狀進(jìn)行的設(shè)計(jì)。這兩塊的校驗(yàn)都前置到Auth系統(tǒng)中,,優(yōu)缺點(diǎn)在上面的小節(jié)也有講述,。最后,架構(gòu)設(shè)計(jì)根據(jù)自己的需求和現(xiàn)狀,,筆者的解決思路僅供參考,。


本文的源碼地址:


  • GitHub:https://github.com/keets2012/Auth-service 

  • 碼云: https:///keets/Auth-Service


參考


  • 微服務(wù)API級(jí)權(quán)限的技術(shù)架構(gòu)

    (http://blog.csdn.net/OmniStack/article/details/77881185)

  • spring-security-oauth

    (http://projects./spring-security-oauth/docs/oauth2.html)

  • Spring-Security Docs

    (http://projects./spring-security/)


原文鏈接:http:///2017/10/24/security3/


深入學(xué)習(xí)Kubernetes

640?wx_fmt=png


本次培訓(xùn)內(nèi)容包含:Kubernetes架構(gòu)、Kubernetes安裝,、Kubernetes功能導(dǎo)覽,、監(jiān)控解決方案、Kubernetes高階——設(shè)計(jì)和實(shí)現(xiàn),、Kubernetes落地實(shí)踐等,,點(diǎn)擊識(shí)別下方二維碼加微信好友了解具體培訓(xùn)內(nèi)容



點(diǎn)擊閱讀原文鏈接即可報(bào)名,。 

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多