springCloud微服務系列——OAuth2+JWT模式下的swagger+feign處理

    這次總結的內容爲通過spring-security實現的OAuth2+JWT認證服務器和資源服務器分離架構下,如何引入swagger+feign。

    需要解決的問題:

    1、swagger-ui.html不需要權限驗證

    2、swagger需要提供request頭的Authorization參數的輸入框來輸入令牌

    3、通過feign調用其他微服務時,被調用服務不再需要權限認證

    一、swagger-ui.html繞過權限驗證

    這個問題解決起來比較簡單,由於這裏使用的是spring-security,那麼只需要在認證服務器的安全配置中繞過相關的資源即可

.antMatchers(
					 Constants.LOGIN_CONTROLLER,
					 Constants.IMAGE_CODE_CONTROLLER+"/**",
					 Constants.SMS_CODE_CONTROLLER+"/**",
					 "/swagger-ui.html",
					 "/swagger-resources/**",
					 "/v2/api-docs",
					 "/oauth/check_token").permitAll()

    二、swagger提供request頭的Authorization參數輸入框

      這個問題也好解決,兩個辦法,一個是每個rest api上進行註釋聲明,一個是通過java config統一進行配置。第一種方法沒什麼好說的,這裏說說第二種方法,只需要做如下配置即可

@Bean
    public Docket createRestApi() {
		ParameterBuilder authorizationPar = new ParameterBuilder();  
        List<Parameter> pars = new ArrayList<Parameter>();    
        authorizationPar.name("Authorization").description("Authorization")  
        .modelRef(new ModelRef("string")).parameterType("header")   
        .required(false).build(); 
        pars.add(authorizationPar.build());    
		
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(MultiRequestHandlerSelectors.basePackage(serverCoreProperties.getSwagger().getBasePackages()))
                .paths(PathSelectors.any())
                .build()
                .globalOperationParameters(pars);
    }

    三、微服務間通過feign調用時,被調用服務繞過權限驗證

        思路是這樣的,通過feign調用其他服務的時候,調用一個攔截器,在攔截器中把token傳入request頭的Authorization參數中。這裏的攔截器爲feign.RequestInterceptor,實現代碼舉例如下

public class SsoFeignConfig implements RequestInterceptor {

	public static String TOKEN_HEADER = "authorization";
	
	@Override
	public void apply(RequestTemplate template) {
		template.header(TOKEN_HEADER, getHeaders(getHttpServletRequest()).get(TOKEN_HEADER));
	}

	private HttpServletRequest getHttpServletRequest() {
        try {
            return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        } catch (Exception e) {
            return null;
        }
    }
	
	private Map<String, String> getHeaders(HttpServletRequest request) {
        Map<String, String> map = new LinkedHashMap<>();
        Enumeration<String> enumeration = request.getHeaderNames();
        while (enumeration.hasMoreElements()) {
            String key = enumeration.nextElement();
            String value = request.getHeader(key);
            map.put(key, value);
        }
        return map;
    }
	
}

  在調用方聲明微服務的時候通過@FeignClient註釋的configuration屬性指定攔截器

@FeignClient(name="user-server/userApi", fallback=UserServiceImpl.class, configuration = SsoFeignConfig.class)
public interface UserService {

	@GetMapping("/user/name/{username}")
	public SimpleResponse getByusername(@PathVariable("username") String username);
	
}

@FeignClient中的name爲微服務的服務名+微服務的contextPath,fallback爲服務調用失敗的處理類,configuration用來指定攔截器

到此爲止,OAuth2+JWT模式下的swagger+feign處理就完成了


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章