[英]How can a microservice use the security config of another microservice
我有一個用戶微服務,處理與用戶相關的所有事情,包括安全性(創建用戶,登錄,重設密碼...)。 我正在使用JWT令牌進行安全保護。
我的配置安全性如下所示:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(
securedEnabled = true,
jsr250Enabled = true,
prePostEnabled = true
)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
CustomUserDetailsService customUserDetailsService;
@Autowired
private JwtAuthenticationEntryPoint unauthorizedHandler;
@Bean
public JwtAuthenticationFilter jwtAuthenticationFilter() {
return new JwtAuthenticationFilter();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
/**
* the main Spring Security interface for authenticating a user
*
* @return the {@link AuthenticationManager}
* @throws Exception
*/
@Bean(BeanIds.AUTHENTICATION_MANAGER)
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
/**
* create an AuthenticationManager instance
*
* @param auth AuthenticationManagerBuilder used to create the instance of AuthenticationManager
* @throws Exception
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(customUserDetailsService)
.passwordEncoder(passwordEncoder());
}
/**
* configure security functionality, add rules to protect resources
* define what route can be accessed without authentication
*
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.headers().frameOptions().disable();
http
.cors()
.and()
.csrf()
.disable()
.exceptionHandling()
.authenticationEntryPoint(unauthorizedHandler)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/h2-console/**")
.permitAll()
.antMatchers("/api/auth/**")
.permitAll()
.antMatchers(HttpMethod.GET, "/api/user/**")
.permitAll()
.anyRequest()
.authenticated();
// Add our custom JWT security filter
http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
我要做的是使用用戶微服務來保護另一個微服務(目前是基本的CRUD)。
我在CRUD微服務中創建了偽裝界面
@FeignClient(name="UserMicroservice", url="http://localhost:8080")
public interface UserClient {
@PostMapping(value = "/api/auth/login")
AuthTokenDto authenticateUser(@RequestBody LogInDto logInDto);
}
和一個控制器
@RestController
public class AuthController {
@Autowired
UserClient userClient;
@PostMapping("/api/auth/login")
public AuthTokenDto authenticate(@RequestBody LogInDto logInDto) {
AuthTokenDto token = userClient.authenticateUser(logInDto);
return token;
}
}
這可以成功調用用戶微服務並獲取jwt令牌。
但是,我不知道如何讓我的CRUD微服務使用用戶微服務的安全配置。
因此,從本質上講,我該怎么做才能使用用戶微服務保護CRUD微服務的端點?
到目前為止,我還無法自行找到解決方案或無法搜索互聯網。
我建議您將令牌保存在redis數據庫中並在所有微服務中實現安全層,並且每次您的微服務收到請求時,如果令牌存在,則實現JWT的類將在redis中進行搜索。
我這樣實現
public class JWTAuthorizationFilter extends BasicAuthenticationFilter{
public JWTAuthorizationFilter(AuthenticationManager authenticationManager) {
super(authenticationManager);
}
@Override
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain)
throws IOException, ServletException {
String header = req.getHeader(Constantes.HEADER_AUTHORIZACION_KEY);
Logger.getLogger(JWTAuthorizationFilter.class.getCanonicalName()).log(Level.INFO, "HEADER: "+header);
if (header == null || !header.startsWith(Constantes.TOKEN_BEARER_PREFIX)) {
chain.doFilter(req, res);
return;
}
UsernamePasswordAuthenticationToken authentication = getAuthentication(req);
SecurityContextHolder.getContext().setAuthentication(authentication);
chain.doFilter(req, res);
}
private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
String token = request.getHeader(Constantes.HEADER_AUTHORIZACION_KEY);
Logger.getLogger(JWTAuthorizationFilter.class.getCanonicalName()).log(Level.INFO, "token: "+token);
if (token != null) {
// Se procesa el token y se recupera el usuario.
Jedis jedis = new Jedis(SystemVariables.getDataBaseRedisIp());
String key = jedis.get(token);
Logger.getLogger(JWTAuthorizationFilter.class.getCanonicalName()).log(Level.INFO, "key: "+key);
String user = JWT.require(Algorithm.HMAC256(key)).build()
.verify(token.replace(Constantes.TOKEN_BEARER_PREFIX, ""))
.getSubject();
if (user != null) {
return new UsernamePasswordAuthenticationToken(user, null, new ArrayList<>());
}
return null;
}
return null;
}
並在每個http請求上添加標題Authorization以及生成的令牌,例如:
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImV4cCI6MTU2NDEwNjMzNX0.HzG2nKUReCsrEZZOQLH8cuh3yfuP4VX0tkDvWTS8_s8
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.