最初,spring security的身份验证中的主要对象是一个字符串,它只包含用户ID。通过定义自定义用户详细信息服务或自定义身份验证提供程序并在spring security中扩展用户对象,用户信息应存储在主体对象中。但无论我选择哪一个,主要对象总是保持一个字符串。为了安全起见,我们使用带有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));
}
}
这是我的网络安全配置:
@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总是返回同一个人,但我认为这应该不是问题。
答案 0 :(得分:1)
声明CustomAuthenticationProvider
只会将Authentication
对象添加到安全上下文中。为了在安全上下文中自定义所需的Principal
对象,您必须实现UserDetailsService
。
Baeldung是一本很好的入门书。