spring-boot - Spring Boot Oauth2 资源服务器 UserDetailsService
问题描述
试图让 UserDetailsService 为我设置的 oauth2 资源服务器工作。我能够成功地对 jwt 进行身份验证,但我似乎没有做任何事情来让它调用 loadUserByUsername 方法。这最初是使用 SAML 并且可以正常工作,但是现在我已经切换到 Oauth2 并且无法正常工作。
@Service
public class OauthUsersDetailsServiceImpl implements UserDetailsService{
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//some user loading junk here - this is never called
}
}
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception
{
//test key for now
SecretKeySpec key = new SecretKeySpec("private key0000000000000000000000000000000".getBytes(), "HMACSHA256");
http
.authorizeRequests()
.antMatchers(/*some endpoints im excluding from auth - this all works*/)
.permitAll().and()
.authorizeRequests()
.anyRequest().authenticated().and()
.oauth2ResourceServer().jwt().decoder(NimbusJwtDecoder.withSecretKey(key).build());
}
}
我在 google 上发现我可以使用 @service 将类注册为一个 bean,spring 会选择它,但它不起作用。我也尝试通过 AuthenticationManagerBuilder 添加它,但这也不起作用。我的猜测是,它的 jwt 方面有它自己的 UserDetailsService ,它已经实现并且优先于我的。也就是说,让我调用的正确方法是什么,或者在身份验证完成后以某种方式手动调用我的用户加载逻辑并覆盖 Principal 对象是否更好?我需要在调用端点之前执行此操作,以便 PreAuthorize 可以检查 UserDetailsService 加载的角色。
解决方案
弄清楚了。希望这将帮助遇到同样问题的任何人。我必须在链中添加一个自定义过滤器来调用我的用户详细信息服务并覆盖上下文:
public class Oauth2AuthorizationFilter extends GenericFilterBean {
@Autowired
private OauthUsersDetailsServiceImpl oauthUsersDetailsServiceImpl;
public Oauth2AuthorizationFilter (OauthUsersDetailsServiceImpl userDetailsService) {
this.oauthUsersDetailsServiceImpl = userDetailsService;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
SecurityContext context = SecurityContextHolder.getContext();
if(context.getAuthentication() != null && !(context.getAuthentication().getPrincipal() instanceof Users)) {
UserDetails user = oauthUsersDetailsServiceImpl.loadUserByUsername(((Jwt)context.getAuthentication().getPrincipal()).getClaimAsString("user_name"));
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
context.setAuthentication(authentication);
}
chain.doFilter(request, response);
}
}
@Override
protected void configure(HttpSecurity http) throws Exception
{
//test key for now
SecretKeySpec key = new SecretKeySpec("private key0000000000000000000000000000000".getBytes(), "HMACSHA256");
http.authorizeRequests().antMatchers(/*bunch of junk...*/).permitAll().and().authorizeRequests().anyRequest().authenticated().and()
.oauth2ResourceServer().jwt().decoder(NimbusJwtDecoder.withSecretKey(key).build());
http.addFilterAfter(jwtAuthTokenFilterBean(), SwitchUserFilter.class);
}
这终于做了我需要的
推荐阅读
- java - 正则表达式提取字符的第一次和最后一次出现之间的字符串
- javascript - PhantomJS 返回错误的文本
- python-3.x - 基于比较从另一个嵌套列表中获得的值从嵌套列表中删除项目
- spring - 如何在spring数据中指定javax.persistence.lock.scope
- wordpress - 如何更改撇号主题的帖子标题:Wordpress
- angular - 星云授权问题(总是成功登录) - ngx-admin
- spring - Spring Boot 应用程序属性加载过程以编程方式更改以提高安全性
- css - 如何在html中的页面顶部添加一个乐队
- reactjs - 是否可以在 react-spring 中设置 100% 的动画?
- android - 无法实现 Twilio StatusCallback