功能
- 某個rest介面是公開的,它的feign服務的介面需要授權
- 重寫一個HttpServletRequestWrapper,實作模擬登錄之后把header頭進行填充
- 介面請求背景關系里的token,通過Feign攔截器轉給每個feign請求背景關系
- 完成對feign介面的自動授權訪問
重寫HttpServletRequestWrapper
/**
* 自定義的請求背景關系.
*/
public class CustomHttpServletRequest extends HttpServletRequestWrapper {
private Map<String, String> headers = new HashMap<>();
public CustomHttpServletRequest(HttpServletRequest request) {
super(request);
}
public void addHeader(String name, String value) {
headers.put(name, value);
}
@Override
public String getHeader(String name) {
String value = https://www.cnblogs.com/lori/p/super.getHeader(name);
if (headers.containsKey(name)) {
value = headers.get(name);
}
return value;
}
@Override
public Enumeration getHeaderNames() {
List names = Collections.list(super.getHeaderNames());
names.addAll(headers.keySet());
return Collections.enumeration(names);
}
@Override
public Enumeration getHeaders(String name) {
List list = Collections.list(super.getHeaders(name));
if (headers.containsKey(name)) {
list.add(headers.get(name));
}
return Collections.enumeration(list);
}
}
建立過濾器
@Component
public class CustomFilter implements Filter {
@Autowired
KcUserClient kcUserClient;
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
CustomHttpServletRequest request = new CustomHttpServletRequest((HttpServletRequest) servletRequest);
request.addHeader("Authorization", "Bearer " + login().getAccessToken());
filterChain.doFilter(request, servletResponse);
}
public KeycloakAccessToken login() {
// 登陸引數省略
var result = kcUserClient.login(authTokenRequest);
return result;
}
}
WebMvcConfigurer里注冊
對/add介面進行配置
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Resource
private CustomFilter customFilter;
@Bean
public FilterRegistrationBean<CustomFilter> initFilterRegistrationBean() {
FilterRegistrationBean<CustomFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(customFilter);
registrationBean.addUrlPatterns("/add");
registrationBean.setOrder(0);
return registrationBean;
}
}
Feign攔截器的配置
/**
* @description: Feign內部呼叫時帶上請求頭資訊
* 注意:要去yml里面改變hystrix Feign的隔離策為strategy: SEMAPHORE
**/
@Configuration
public class FeignConfiguration implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder
.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
Enumeration<String> headerNames = request.getHeaderNames();
if (headerNames != null) {
while (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
String values = request.getHeader(name);
template.header(name, values);
}
}
Enumeration<String> bodyNames = request.getParameterNames();
StringBuffer body = new StringBuffer();
if (bodyNames != null) {
while (bodyNames.hasMoreElements()) {
String name = bodyNames.nextElement();
String values = request.getParameter(name);
body.append(name).append("=").append(values).append("&");
}
}
if (body.length() != 0) {
body.deleteCharAt(body.length() - 1);
template.body(body.toString());
}
}
}
上面代碼完成了對/add介面的攔截,通過自動授權,完成對授權介面kcUserClient.addUser();呼叫,
KcUserClient內容
@FeignClient(name = "keycloak", url = "http://192.168.4.26:8080/auth", configuration = KcUserClient.Configuration.class)
public interface KcUserClient {
@PostMapping("/admin/realms/demo/users")
ResponseEntity<?> addUser(@RequestBody UserDTO userDTO);
@RequestMapping(value = "https://www.cnblogs.com/realms/demo/protocol/openid-connect/token",
method = RequestMethod.POST,
consumes = "application/x-www-form-urlencoded")
KeycloakAccessToken login(@RequestBody AuthTokenRequest authTokenRequest);
/**
* 轉向器.
*/
class Configuration {
@Bean
Encoder feignFormEncoder(ObjectFactory<HttpMessageConverters> converters) {
return new SpringFormEncoder(new SpringEncoder(converters));
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/263635.html
標籤:Java
