<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # :-: Gateway校驗token 訪問認證服務拿到token之后 訪問資源服務(各個微服務 訂單服務)攜帶header 網關負責對token的校驗工作。 目標是校驗token并將其解密之后傳給服務。校驗token jwt有自帶的。其實自己也能實現。jwt由3部分組成都有一個點分隔。原理是第一部分base64加密 加上一個點 再加上第二部分的base64加密 利用私鑰簽名。所以我們只要驗第三部分,利用RSA公鑰驗簽就行了。 #### **1、資源服務器配置** ***** ~~~ package com.hjf.gateway.auth; import cn.hutool.core.util.ArrayUtil; import com.hjf.gateway.auth.component.RestAuthenticationEntryPoint; import com.hjf.gateway.auth.component.RestfulAccessDeniedHandler; import com.hjf.gateway.auth.constant.AuthConstant; import lombok.AllArgsConstructor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.convert.converter.Converter; import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; import org.springframework.security.config.web.server.ServerHttpSecurity; import org.springframework.security.oauth2.jwt.Jwt; import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter; import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter; import org.springframework.security.oauth2.server.resource.authentication.ReactiveJwtAuthenticationConverterAdapter; import org.springframework.security.web.server.SecurityWebFilterChain; import reactor.core.publisher.Mono; /** * 資源服務器配置 * Created by macro on 2020/6/19. */ @AllArgsConstructor @Configuration @EnableWebFluxSecurity public class ResourceServerConfig { private final AuthorizationManager authorizationManager; private final IgnoreUrlsConfig ignoreUrlsConfig; private final RestfulAccessDeniedHandler restfulAccessDeniedHandler; private final RestAuthenticationEntryPoint restAuthenticationEntryPoint; // private final IgnoreUrlsRemoveJwtFilter ignoreUrlsRemoveJwtFilter; @Bean public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { http.oauth2ResourceServer().jwt().jwtAuthenticationConverter(jwtAuthenticationConverter()); //自定義處理JWT請求頭過期或簽名錯誤的結果 http.oauth2ResourceServer().authenticationEntryPoint(restAuthenticationEntryPoint); //對白名單路徑,直接移除JWT請求頭 //http.addFilterBefore(ignoreUrlsRemoveJwtFilter, SecurityWebFiltersOrder.AUTHENTICATION); http.authorizeExchange() .pathMatchers(ArrayUtil.toArray(ignoreUrlsConfig.getUrls(),String.class)).permitAll()//白名單配置 .anyExchange().access(authorizationManager)//鑒權管理器配置 .and().exceptionHandling() .accessDeniedHandler(restfulAccessDeniedHandler)//處理未授權 .authenticationEntryPoint(restAuthenticationEntryPoint)//處理未認證 .and().csrf().disable(); return http.build(); } @Bean public Converter<Jwt, ? extends Mono<? extends AbstractAuthenticationToken>> jwtAuthenticationConverter() { JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter(); jwtGrantedAuthoritiesConverter.setAuthorityPrefix(AuthConstant.AUTHORITY_PREFIX); jwtGrantedAuthoritiesConverter.setAuthoritiesClaimName(AuthConstant.AUTHORITY_CLAIM_NAME); JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter(); jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter); return new ReactiveJwtAuthenticationConverterAdapter(jwtAuthenticationConverter); } } ~~~ #### **2、鑒權管理器** ***** ~~~ package com.hjf.gateway.auth; import cn.hutool.core.collection.ConcurrentHashSet; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.security.authorization.AuthorizationDecision; import org.springframework.security.authorization.ReactiveAuthorizationManager; import org.springframework.security.core.Authentication; import org.springframework.security.web.server.authorization.AuthorizationContext; import org.springframework.stereotype.Component; import org.springframework.util.AntPathMatcher; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; import java.util.Set; /** * 功能說明:【鑒權管理器,用于判斷是否有資源的訪問權限】 * 作 者:lihaijun * 創建日期:2020-11-20 */ @Slf4j @Component public class AuthorizationManager implements ReactiveAuthorizationManager<AuthorizationContext> { @Autowired private RedisTemplate<String,Object> redisTemplate; private Set<String> permitAll = new ConcurrentHashSet<>(); private static final AntPathMatcher antPathMatcher = new AntPathMatcher(); /** * 實現權限驗證判斷 */ @Override public Mono<AuthorizationDecision> check(Mono<Authentication> authenticationMono, AuthorizationContext authorizationContext) { ServerWebExchange exchange = authorizationContext.getExchange(); //請求資源 String requestPath = exchange.getRequest().getURI().getPath(); // 是否直接放行 if (permitAll(requestPath)) { return Mono.just(new AuthorizationDecision(true)); } return authenticationMono.map(auth -> { return new AuthorizationDecision(checkAuthorities(exchange, auth, requestPath)); }).defaultIfEmpty(new AuthorizationDecision(false)) ; } /** * 校驗是否屬于靜態資源 * @param requestPath 請求路徑 */ private boolean permitAll(String requestPath) { return permitAll.stream().filter(r -> antPathMatcher.match(r, requestPath)).findFirst().isPresent(); } //權限校驗 private boolean checkAuthorities(ServerWebExchange exchange, Authentication auth, String requestPath) { // if(auth instanceof OAuth2Authentication){ // OAuth2Authentication athentication = (OAuth2Authentication) auth; // String clientId = athentication.getOAuth2Request().getClientId(); // log.info("clientId is {}",clientId); // } Object principal = auth.getPrincipal(); log.info("用戶信息:{}",principal.toString()); return true; } } ~~~ #### **3、認證結果處理** ``` 3.1 沒有登錄或token過期時 ``` ~~~ package com.hjf.gateway.auth.component; import cn.hutool.json.JSONUtil; import com.hjf.frame.base.BaseResp; import org.springframework.core.io.buffer.DataBuffer; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.server.ServerAuthenticationEntryPoint; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; import java.nio.charset.Charset; /** * 功能說明:【自定義返回結果:沒有登錄或token過期時】 * 作 者:lihaijun * 創建日期:2020-11-20 */ @Component public class RestAuthenticationEntryPoint implements ServerAuthenticationEntryPoint { @Override public Mono<Void> commence(ServerWebExchange exchange, AuthenticationException e) { ServerHttpResponse response = exchange.getResponse(); response.setStatusCode(HttpStatus.OK); response.getHeaders().add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); // String body= JSONUtil.toJsonStr(CommonResult.unauthorized(e.getMessage())); String body= JSONUtil.toJsonStr(BaseResp.failMsg("暫未登錄或token已經過期")); DataBuffer buffer = response.bufferFactory().wrap(body.getBytes(Charset.forName("UTF-8"))); return response.writeWith(Mono.just(buffer)); } } ~~~ ``` 3.2 沒有權限訪問時限 ``` ~~~ package com.hjf.gateway.auth.component; import cn.hutool.json.JSONUtil; import com.hjf.frame.base.BaseResp; import org.springframework.core.io.buffer.DataBuffer; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.web.server.authorization.ServerAccessDeniedHandler; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; import java.nio.charset.Charset; /** * 功能說明:【自定義返回結果:沒有權限訪問時限】 * 作 者:lihaijun * 創建日期:2020-11-20 */ @Component public class RestfulAccessDeniedHandler implements ServerAccessDeniedHandler { @Override public Mono<Void> handle(ServerWebExchange exchange, AccessDeniedException denied) { ServerHttpResponse response = exchange.getResponse(); response.setStatusCode(HttpStatus.OK); response.getHeaders().add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); String body= JSONUtil.toJsonStr(BaseResp.failMsg("沒有相關權限")); DataBuffer buffer = response.bufferFactory().wrap(body.getBytes(Charset.forName("UTF-8"))); return response.writeWith(Mono.just(buffer)); } } ~~~ #### **4、認證后續處理** ~~~ package com.hjf.gateway.filter; import cn.hutool.core.util.StrUtil; import com.nimbusds.jose.JWSObject; import lombok.extern.slf4j.Slf4j; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.core.Ordered; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; import java.text.ParseException; /** * 功能說明:【將登錄用戶的JWT轉化成用戶信息的全局過濾器】 * 作 者:lihaijun * 創建日期:2020-11-20 */ @Slf4j @Component public class AuthGlobalFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); String url = request.getPath().pathWithinApplication().value(); String token = exchange.getRequest().getHeaders().getFirst("Authorization"); if (StrUtil.isEmpty(token)) { return chain.filter(exchange); } //swagger文檔請求 放過 if (url.endsWith("v2/api-docs")){ return chain.filter(exchange); } try { //從token中解析用戶信息并設置到Header中去 String realToken = token.replace("Bearer ", ""); JWSObject jwsObject = JWSObject.parse(realToken); String userStr = jwsObject.getPayload().toString(); log.info("AuthGlobalFilter.filter() user:{}",userStr); request.mutate().header("user", userStr).build(); exchange = exchange.mutate().request(request).build(); } catch (ParseException e) { e.printStackTrace(); } return chain.filter(exchange); } @Override public int getOrder() { return 0; } } ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看