问题描述
我有一个资源服务器,它正在接收带有有效承载令牌的请求。我可以将 @AuthenticationPrincipal Jwt token
用于需要从令牌中获取声明的所有请求,或者我应该能够从 SecurityContextHolder
获取用户信息,对吗?我想从上下文持有者那里得到它。我假设我需要在我的 SecurityConfig
中定义 jwt 转换器?我找不到有关推荐方法的任何信息。
here 中的代码适用于一些旧版本的 Spring Security...我正在使用最新的 Spring Boot 和 Spring security 5.4.2
@Configuration
@EnableWebSecurity
@Order(1)
public class JwtSecurityConfig extends WebSecurityConfigurerAdapter {
@Value("${spring.security.oauth2.resourceserver.jwt.jwk-set-uri}")
private String jwkSetUri;
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic().disable()
.formLogin(AbstractHttpConfigurer::disable)
.csrf(AbstractHttpConfigurer::disable)
.authorizeRequests(authorize -> authorize
.mvcMatchers(HttpMethod.GET,"/test/**").authenticated()
.mvcMatchers(HttpMethod.POST,"/test/**").authenticated()
)
.oauth2ResourceServer().jwt().jwtAuthenticationConverter(jwtAuthenticationConverter());
}
private JwtAuthenticationConverter jwtAuthenticationConverter() {
JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
jwtGrantedAuthoritiesConverter.setAuthoritiesClaimName("entGrps");
jwtGrantedAuthoritiesConverter.setAuthorityPrefix("ROLE_");
JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter);
return jwtAuthenticationConverter;
}
@Bean
public JwtDecoder jwtDecoder() {
return NimbusJwtDecoder.withJwkSetUri(this.jwkSetUri).build();
}
}
解决方法
如果您打算使用 spring-security-oauth2-resource-server 依赖项,
我认为最好使用 @AuthenticationPrincipal Jwt token
来获取令牌的声明。
这更简单,样板代码更少。
但这取决于您,Imranmadbar 的解决方案也有效)
,如果您想要来自 SecurityContextHolder 的信息,您必须将其保留在那里。
这是针对此问题的最简单的解决方案:
- 从请求中获取身份验证令牌,其中显示了您的当前日志用户信息。
- 使用一些Util方法从jwt中提取日志用户名。
- 使用此用户名从数据库中获取用户详细信息。
- 最后将此用户信息设置为到 Spring Security 上下文持有者中。
并且您必须使用 HTTP 请求过滤器 (OncePerRequestFilter) 对每个请求执行此操作。
喜欢:
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import com.madbarsoft.config.MyUserDetailsService;
import com.madbarsoft.utility.JwtUitl;
@Component
public class JwtRequestFilter extends OncePerRequestFilter {
@Autowired
private JwtUitl jwtUitl;
@Autowired
private MyUserDetailsService userDetailsService;
@Override
protected void doFilterInternal(HttpServletRequest request,HttpServletResponse response,FilterChain chin)
throws ServletException,IOException {
final String authorizationHeader = request.getHeader("Authorization");
System.out.println("Authorization Header #:"+authorizationHeader);
String userName = null;
String jwtStr = null;
if(authorizationHeader != null && authorizationHeader.startsWith("Bearer ")){
jwtStr = authorizationHeader.substring(7);
userName = jwtUitl.extractUserName(jwtStr);
System.out.println("Form JWT userName: "+userName);
}
System.out.println("In Filter Before set #: "+SecurityContextHolder.getContext().getAuthentication());
if(userName != null && SecurityContextHolder.getContext().getAuthentication() == null){
UserDetails userDetails = this.userDetailsService.loadUserByUsername(userName);
if(jwtUitl.validateToken(jwtStr,userDetails)){
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
userDetails,null,userDetails.getAuthorities());
usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
System.out.println("In Filter After Set #: "+SecurityContextHolder.getContext().getAuthentication());
}
chin.doFilter(request,response);
}
}
现在您可以从整个项目的任何位置访问用户信息。
(这是一个正在运行的项目,您可以从 gitLink 此处获取一些信息。)