我有一个设置,我需要在其中进行租户感知的身份验证和授权。
@Order(Ordered.LOWEST_PRECEDENCE - 100)
public class TenantFilter extends OncePerRequestFilter {
private static final Logger logger = LoggerFactory.getLogger(TenantFilter.class);
private static final String TENANT_HEADER = "X-Tenant";
private static final String CONNECTION_STRING = "ObfuscatedConnectionString";
private static final String TENANT_REPLACEMENT = "TENANT";
@Override
protected void doFilterInternal (HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String dbConnectionString = CONNECTION_STRING.replace(TENANT_REPLACEMENT, "");
ConnectionStorage.setConnection(dbConnectionString);
filterChain.doFilter(request, response);
ConnectionStorage.clear();
}
}
虽然我知道有一些地方可以改进,但这只是一个占位符,以便能够测试该机制。2实际的实现将在后面进行。3当在不需要添加JWT的情况下进行测试时,它可以按预期工作,并且在给定正确的前提条件的情况下根据请求切换承租人。
但是,我不想在每个请求上都发送用户名+密码,而想在混合中添加一个JWT。
public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private static final Logger logger = LoggerFactory.getLogger(JwtAuthenticationFilter.class);
private AuthenticationManager authenticationManager;
public JwtAuthenticationFilter (AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
@Override
public Authentication attemptAuthentication (HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
logger.info("Attempting authentication");
try {
UserRequest creds = new ObjectMapper()
.readValue(request.getInputStream(), UserRequest.class);
return authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
creds.getUsername(),
creds.getPassword(),
new ArrayList<>())
);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
protected void successfulAuthentication (HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication auth) throws IOException, ServletException {
logger.info("Authentication successful");
String token = JWT.create()
.withSubject(((User) auth.getPrincipal()).getUsername())
.withExpiresAt(new Date(System.currentTimeMillis() + (JWTConstants.ACCESS_TOKEN_VALIDITY_SECONDS * 1000)))
.sign(Algorithm.HMAC512(JWTConstants.SIGNING_KEY.getBytes()));
response.addHeader(JWTConstants.HEADER_STRING, JWTConstants.TOKEN_PREFIX + token);
}
}
和
public class JwtAuthorizationFilter extends BasicAuthenticationFilter {
private static final Logger logger = LoggerFactory.getLogger(JwtAuthorizationFilter.class);
public JwtAuthorizationFilter (AuthenticationManager authenticationManager) {
super(authenticationManager);
}
@Override
protected void doFilterInternal (HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
logger.info("Doing filter internal");
String header = request.getHeader(JWTConstants.HEADER_STRING);
if (header == null || !header.startsWith(JWTConstants.TOKEN_PREFIX)) {
chain.doFilter(request, response);
return;
}
UsernamePasswordAuthenticationToken authentication = getAuthentication(request);
SecurityContextHolder.getContext().setAuthentication(authentication);
chain.doFilter(request, response);
}
private UsernamePasswordAuthenticationToken getAuthentication (HttpServletRequest request) {
String token = request.getHeader(JWTConstants.HEADER_STRING);
if (token != null) {
// parse the token.
String user = JWT.require(Algorithm.HMAC512(JWTConstants.SIGNING_KEY.getBytes()))
.build()
.verify(token.replace(JWTConstants.TOKEN_PREFIX, ""))
.getSubject();
if (user != null) {
return new UsernamePasswordAuthenticationToken(user, null, new ArrayList<>());
}
return null;
}
return null;
}
}
为我的请求提供身份验证。在/api/user/login中有一个用户名和密码,还有一个jwt标记用于其他所有内容。
然而,看起来好像首先执行安全过滤器,并且我的承租人过滤器对于设置要转到的正确DB的connectionstring相当重要。
版本:springframework。 Boot :2.6.2
1条答案
按热度按时间7d7tgy0s1#
你可以看看这个答案:https://stackoverflow.com/a/59340951这将使您能够最大限度地控制过滤器的执行时间。
我想(但我可能错了)
@Order(Ordered.HIGHEST_PRECEDENCE)
也可能会起作用。虽然措辞有点奇怪,但Ordered.HIGHEST_PRECEDENCE
会给你Integer.MIN_VALUE
,较低的值会先执行。顺便说一句,在编写您自己的JWT验证过滤器之前,还请查看Spring Security的OAuth 2.0功能(除非您有特定的情况):https://docs.spring.io/spring-security/reference/6.0.0-M1/servlet/oauth2/resource-server/jwt.html#oauth2resourceserver-jwt-minimalconfiguration