最初,spring Security身份验证中的principal对象是一个字符串,它只包含用户id。通过定义自定义用户详细信息服务或自定义身份验证提供程序,并扩展spring Security中的用户对象,用户信息应该存储在principal对象中。但无论我选择哪一个,principal对象总是保持字符串。2为了安全起见,我们使用了带有oauth2的身份验证服务器。
这是一个带有自定义身份验证提供程序的版本。我已经找到了一个提示,一个名为forcePrincipleAsString的字段可能是我的问题的原因,尽管它最初应该被设置为false,而我使用的自定义身份验证提供程序没有这样的字段。
这是我的自定义身份验证提供程序:
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
public Authentication authenticate(Authentication authentication ) throws AuthenticationException {
String password = authentication.getCredentials().toString().trim();
SecurityUser appUser = new SecurityUser();
return new UsernamePasswordAuthenticationToken(appUser, password, new ArrayList<>());
}
@Override
public boolean supports(Class<? extends Object> authentication) {
return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
}
}
这是我的Web安全配置:
@Configuration
@EnableOAuth2Sso
@EnableGlobalMethodSecurity(prePostEnabled = true)
@ComponentScan("edu.kit.tm.cm.bamsg.bffweb.iamservice")
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private static final String REALM = "bam";
@Autowired
private CustomAuthenticationProvider authProvider;
@Autowired
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authProvider);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.logout()
.and()
//endpoints without authentication
.authorizeRequests().antMatchers("/logged", "/userData").permitAll()
.and()
// default with authentication
.authorizeRequests().anyRequest().authenticated()
.and()
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
}
@Bean
public OAuth2FeignRequestInterceptor oAuth2FeignRequestInterceptor(OAuth2ClientContext context, OAuth2ProtectedResourceDetails details) {
return new OAuth2FeignRequestInterceptor(context, details);
}
// I added this code from an advice, but it didn't help
@Bean
BasicAuthenticationEntryPoint getBasicAuthEntryPoint() {
BasicAuthenticationEntryPoint basicAuth = new BasicAuthenticationEntryPoint();
basicAuth.setRealmName(REALM);
return basicAuth;
}
}
扩展的用户类如下所示:
public class SecurityUser extends User{
String firstName;
String name;
String password;
private static final long serialVersionUID = 1L;
public SecurityUser() {
super("user", "none", new ArrayList<>());
firstName = "Rainer";
name = "Schlund";
password = "meins";
}
public String getRole(){
return "Student";
}
}
至少在用System.out.println
在代码行进行身份验证之后,应该已经调用了定制服务,但不幸的是,它们没有被调用。定制服务中的断点从未到达,主体仍然是一个字符串,而不是我的定制用户:
@ComponentScan("edu.kit.tm.cm.bamsg.bffweb.iamservice")
@RestController
@RequestMapping("/api/theses")
public class ThesisController {
@Autowired
private ThesisClient thesisClient;
@Autowired
private ThesisPersonLinker linker;
@Autowired
private ThesisPersonFilter filter;
@GetMapping
@PreAuthorize("hasRole('theses')")
public ResponseEntity<Collection<ThesisFrontendDTO>> findAllTheses() {
System.out.println(SecurityContextHolder.getContext().getAuthentication().getPrincipal());
代码包含了一些测试的简化,比如SecurityPerson总是返回同一个人,但我认为这不应该是一个问题。
1条答案
按热度按时间gajydyqb1#
声明
CustomAuthenticationProvider
只会将Authentication
对象添加到安全上下文中。为了自定义安全上下文中所需的Principal
对象,必须实现UserDetailsService
。Baeldung是一个很好的引物。