我实现自定义AuthenticationProvider
并返回自定义AuthenticationToken
。
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getName();
String password = authentication.getCredentials().toString();
DBUser dbUser = userDao.getUserLDAP(username);
//check password
return new CustomAuthenticationToken(dbUser, password, grantedAuthorities);
}
CustomAuthenticationToken:
public class CustomAuthenticationToken extends AbstractAuthenticationToken {
private DBUser principal;
private String credential;
public CustomAuthenticationToken(DBUser dbUser, String password, Collection<? extends GrantedAuthority> authorities) {
super(authorities);
this.setDetails(dbUser);
this.principal = dbUser;
this.credential = password;
this.setAuthenticated(true);
}
//getters, setters
}
但是当我尝试在控制器中做时:
@GetMapping("/user/current")
public ResponseEntity<Object> currentUser(@AuthenticationPrincipal DBUser dbUser){
return ResponseEntity.ok(dbUser);
}
dbUser
为空,因为方法AuthenticationPrincipalArgumentResolver
中的resolveArguments
public Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer, NativeWebRequest
webRequest, WebDataBinderFactory binderFactory) throws
Exception {
Authentication authentication =
SecurityContextHolder.getContext().getAuthentication();
if (authentication == null) {
return null;
} else {
Object principal = authentication.getPrincipal();
authentication.userAuthentication
是UsernamePasswordAuthenticationToken
的实例(不是我返回的自定义)。
如何放置令牌详细信息,然后从安全上下文中获取令牌?
我使用spring security oauth2 + jwt。
安全配置:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomAuthenticationProvider authenticationProvider;
@Override
protected void configure(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(authenticationProvider);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.NEVER);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/v2/api-docs",
"/configuration/ui",
"/swagger-resources",
"/configuration/security",
"/swagger-ui.html",
"/webjars/**");
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
OAuth配置:
@Configuration
@EnableAuthorizationServer
public class OAuthConfig extends AuthorizationServerConfigurerAdapter {
private static final String CLIENT_ID = "client";
private static final String CLIENT_SECRET = "pwd";
@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
@Bean
public JwtAccessTokenConverter tokenEnhancer() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey(Keys.PRIVATE_KEY);
converter.setVerifierKey(Keys.PUBLIC_KEY);
return converter;
}
@Bean
public JwtTokenStore tokenStore() {
return new JwtTokenStore(tokenEnhancer());
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints.authenticationManager(authenticationManager)
.tokenStore(tokenStore())
.accessTokenConverter(tokenEnhancer());
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) {
security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient(CLIENT_ID)
.secret(new BCryptPasswordEncoder().encode(CLIENT_SECRET))
.scopes("read", "write")
.authorizedGrantTypes("authorization_code", "refresh_token", "password")
.scopes("openid")
.autoApprove(true)
.accessTokenValiditySeconds(20000)
.refreshTokenValiditySeconds(20000);
}
}
谢谢。
答案 0 :(得分:0)
我通过向JWT添加手动附加信息来解决该问题
public class CustomJwtAccessTokenConverter extends JwtAccessTokenConverter {
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
LinkedHashMap<String, Object> additionalInfo = new LinkedHashMap<>(accessToken.getAdditionalInformation());
additionalInfo.put("details", authentication.getUserAuthentication().getDetails());
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
authentication.setDetails(authentication.getUserAuthentication().getDetails());
return super.enhance(accessToken, authentication);
}
}
JwtAccessTokenConverter的实现将我的详细信息放入令牌
在配置中:
@Bean
public JwtAccessTokenConverter tokenEnhancer() {
JwtAccessTokenConverter converter = new CustomJwtAccessTokenConverter();
converter.setSigningKey(Keys.PRIVATE_KEY);
converter.setVerifierKey(Keys.PUBLIC_KEY);
return converter;
}
@Bean
public JwtTokenStore tokenStore() {
return new JwtTokenStore(tokenEnhancer());
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints.authenticationManager(authenticationManager)
.tokenStore(tokenStore())
.accessTokenConverter(tokenEnhancer());
}
在控制器中
@Autowired
private TokenStore tokenStore;
@GetMapping("/user/current")
public ResponseEntity<Object> currentUser(OAuth2Authentication authentication) {
OAuth2AuthenticationDetails auth2AuthenticationDetails = (OAuth2AuthenticationDetails) authentication.getDetails();
Map<String, Object> details = tokenStore.readAccessToken(auth2AuthenticationDetails.getTokenValue()).getAdditionalInformation();
return ResponseEntity.ok(details.get("details"));
}