自定义JWT认证转换器不生效
来源:8-6 前端为例详解授权码流程

叫我滨哥哥
2023-09-15
老师,我这边跟您一样的代码,但是customJwtAuthenticationTokenConverter这个方法一直不会进,导致现在token里没有Role_的角色,是哪里缺少配置了
@Slf4j
@EnableWebSecurity(debug = true)
@RequiredArgsConstructor
@Import(SecurityProblemSupport.class)
@Order(99)
public class ResourceServerConfig extends WebSecurityConfigurerAdapter {
private final SecurityProblemSupport securityProblemSupport;
private final RoleHierarchyService roleHierarchyService;
private final UserDetailsPasswordService userDetailsPasswordService;
private final UserDetailsService userDetailsService;
@Value("${spring.security.oauth2.resourceserver.jwt.jwk-set-uri}")
private String jwkSetUri;
/**
* 主要用来配置资源的安全性
*
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.requestMatchers(req -> req.mvcMatchers("/api/**", "/admin/**"))//匹配这些指定请求,来做下面这些配置
.csrf(AbstractHttpConfigurer::disable)
.formLogin(AbstractHttpConfigurer::disable)
.httpBasic(AbstractHttpConfigurer::disable)
.logout(AbstractHttpConfigurer::disable)
.sessionManagement(sessionManagement -> sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.exceptionHandling(exceptionHandling -> exceptionHandling
.authenticationEntryPoint(securityProblemSupport)
.accessDeniedHandler(securityProblemSupport))
.authorizeRequests(req -> req
.mvcMatchers("/authorize/**").permitAll()
.mvcMatchers("/admin/**").hasAnyAuthority("SCOPE_user.admin", "SCOPE_client.admin")
.mvcMatchers("/api/users/by-email/**").hasAuthority(Constants.AUTHORITY_USER_READ)
.mvcMatchers("/api/users/{username}/**").access("hasRole('" + Constants.AUTHORITY_ADMIN + "') or @userValidationService.checkUsername(authentication, #username)")
.mvcMatchers("/api/**").authenticated()//authenticated() 这个是认证,只要认证过了,就可以访问该资源
.anyRequest().denyAll())//剩下的请求全部拒绝
// .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt)//这个的jwttoken是带scope的,跟没有role那些
//自定义的JWT认证转换器
.oauth2ResourceServer(resourceServer -> resourceServer.jwt().jwtAuthenticationConverter(customJwtAuthenticationTokenConverter()));
;
}
/**
* 自定义JWT认证转换器
*
* @return
*/
private Converter<Jwt, AbstractAuthenticationToken> customJwtAuthenticationTokenConverter() {
return jwt -> {
List<String> userAuthorities = jwt.getClaimAsStringList("authorities");
List<String> scopes = jwt.getClaimAsStringList("scope");
List<GrantedAuthority> combinedAuthorities = Stream.concat(
userAuthorities.stream(),
scopes.stream().map(scope -> "SCOPE_" + scope))
.map(SimpleGrantedAuthority::new)
.collect(Collectors.toList());
String username = jwt.getClaimAsString("user_name");
return new UsernamePasswordAuthenticationToken(username, null, combinedAuthorities);
};
}
@Override
public void configure(WebSecurity web) {
web
.ignoring()
.antMatchers("/resources/**", "/static/**", "/public/**", "/h2-console/**", "/swagger-ui.html", "/swagger-ui/**", "/v3/api-docs/**")
.requestMatchers(PathRequest.toStaticResources().atCommonLocations());
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDetailsService) // 配置 AuthenticationManager 使用 userService
.passwordEncoder(passwordEncoder()) // 配置 AuthenticationManager 使用 userService
.userDetailsPasswordManager(userDetailsPasswordService); // 配置密码自动升级服务
}
/**
* 如果想让 Spring Security OAuth2 支持 password 这种 grant_type ,那么此处必须要暴露出 AuthenticationManager
*
* @return AuthenticationManager
* @throws Exception 异常
*/
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public PasswordEncoder passwordEncoder() {
String idForEncode = "bcrypt";//定义默认的密码编码器
Map<String, PasswordEncoder> encoders = new HashMap<>(2);
encoders.put(idForEncode, new BCryptPasswordEncoder());
encoders.put("noop", NoOpPasswordEncoder.getInstance());
// encoders.put("pbkdf2", new Pbkdf2PasswordEncoder());
// encoders.put("scrypt", new SCryptPasswordEncoder());
// encoders.put("sha256", new StandardPasswordEncoder());
// encoders.put("SHA-1", new MessageDigestPasswordEncoder("SHA-1"));
return new DelegatingPasswordEncoder(idForEncode, encoders);
}
// @ConditionalOnProperty(prefix = "mooc.security", name = "role-hierarchy-enabled", havingValue = "true")
@Bean
public RoleHierarchyImpl roleHierarchy() {
RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
roleHierarchy.setHierarchy(roleHierarchyService.getRoleHierarchyExpr());
return roleHierarchy;
}
@Bean
JwtDecoder jwtDecoder() {
return NimbusJwtDecoder.withJwkSetUri(this.jwkSetUri).build();
}
}
@RequiredArgsConstructor
@EnableAuthorizationServer
@Configuration
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
private final KeyPair keyPair;
private final DataSource dataSource;
private final PasswordEncoder passwordEncoder;
private final AuthenticationManager authenticationManager;
private final UserDetailsService userDetailsService;
/**
* 配置授权服务器的 token 接入点
*
* @param security
* @throws Exception
*/
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security
//获取token不需要权限
.tokenKeyAccess("permitAll()")
//token的校验必须是认证过的
.checkTokenAccess("isAuthenticated()")
//允许表单提交
.allowFormAuthenticationForClients();
}
/**
* 配置 Jdbc 版本的 JdbcClientDetailsService
*
* @param clients
* @throws Exception
*/
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.jdbc(dataSource)
.passwordEncoder(passwordEncoder);
}
/**
* 配置授权访问的接入点
*
* @param endpoints
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
TokenEnhancerChain chain = new TokenEnhancerChain();
chain.setTokenEnhancers(Collections.singletonList(accessTokenConverter()));
endpoints
// .accessTokenConverter(accessTokenConverter())//二选一
.tokenEnhancer(chain)//二选一
.tokenStore(tokenStore()) // 从 token 中读取特定字段构成 Authentication
.authenticationManager(authenticationManager) // 配置认证 manager
.userDetailsService(userDetailsService); // 配置用户
}
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setKeyPair(this.keyPair);
return converter;
}
/**
* 配置密码编码器
*
* @return
*/
@Bean
public JdbcClientDetailsService jdbcClientDetailsService() {
val service = new JdbcClientDetailsService(dataSource);
service.setPasswordEncoder(passwordEncoder);
return service;
}
}
写回答
2回答
-
接灰的电子产品
2023-09-16
使用git 代码试试,应该好用的
00 -
接灰的电子产品
2023-09-16
这里二选一,注释掉了,
endpoints // .accessTokenConverter(accessTokenConverter())//二选一 .tokenEnhancer(chain)//二选一
012023-09-16
相似问题