尽管我在授权标头中提供了承载令牌,但在访问路径 / user 时仍然遇到问题。
下面的安全配置代码段:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(
securedEnabled = true,
jsr250Enabled = true,
prePostEnabled = true
)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Value("${ldap.url}")
private String ldapUrl;
@Value("${ldap.domain}")
private String ldapDomain;
@Value("${ldap.userSearchBase}")
private String ldapSearchBase;
@Value("${ldap.userGroupSearch}")
private String ldapGroupSearch;
@Value("${ldap.searchFilter}")
private String ldapSearchFilter;
@Value("${ldap.managerDn}")
private String ldapManagerDn;
@Value("${ldap.managerPassword}")
private String ldapManagerPassword;
@Autowired
private JwtAuthenticationEntryPoint unauthorizedHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.disable()
.cors()
.disable()
.exceptionHandling()
.authenticationEntryPoint(unauthorizedHandler)
.and()
.authorizeRequests()
.antMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);;
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(activeDirectoryLdapAuthenticationProvider())
.ldapAuthentication()
.userSearchBase(ldapSearchBase)
.groupSearchBase(ldapGroupSearch)
.userSearchFilter(ldapSearchFilter)
.ldapAuthoritiesPopulator(ldapAuthoritiesPopulator())
.contextSource()
.url(ldapUrl)
.managerDn(ldapManagerDn)
.managerPassword(ldapManagerPassword);
}
private LdapAuthoritiesPopulator ldapAuthoritiesPopulator() {
return new LdapAuthoritiesPopulator() {
@Override
public Collection<? extends GrantedAuthority> getGrantedAuthorities(DirContextOperations userData,
String username) {
return Arrays.asList(new SimpleGrantedAuthority("ROLE_USER"));
}
};
}
@Bean
public AuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider(ldapDomain, ldapUrl);
provider.setConvertSubErrorCodesToExceptions(true);
provider.setUseAuthenticationRequestCredentials(true);
return provider;
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
当我发布到以下网址时,令牌已成功生成: http://localhost:8085/api/auth/generatetoken
但是,当我想使用其他资源(如用户)(请求路径 / user )时,尽管提供了正确的令牌(请参见上图),但我还是未经授权的。
在两个控制器下面,一个用于生成令牌,另一个仅显示用户名字:
生成令牌:
@RestController
@RequestMapping("/api/auth")
public class AuthController {
@Autowired
AuthenticationManager authenticationManager;
@Autowired
JwtTokenProvider tokenProvider;
@SuppressWarnings({ "unchecked", "rawtypes" })
@PostMapping("/generatetoken")
public ResponseEntity<?> authenticateUser(@RequestBody LoginRequest loginRequest) {
if(loginRequest.getUsername().isEmpty() || loginRequest.getPassword().isEmpty()) {
return new ResponseEntity(new ApiResponse(false, MessageConstants.USERNAME_OR_PASSWORD_INVALID),
HttpStatus.BAD_REQUEST);
}
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
loginRequest.getUsername(),
loginRequest.getPassword()
)
);
String jwt = tokenProvider.generateToken(authentication);
return ResponseEntity.ok(new JwtAuthenticationResponse(jwt));
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@PostMapping("/validatetoken")
public ResponseEntity<?> getTokenByCredentials(@Valid @RequestBody ValidateTokenRequest validateToken) {
String username = null;
String jwt =validateToken.getToken();
if (StringUtils.hasText(jwt) && tokenProvider.validateToken(jwt)) {
username = tokenProvider.getUsernameFromJWT(jwt);
//If required we can have one more check here to load the user from LDAP server
return ResponseEntity.ok(new ApiResponse(Boolean.TRUE,MessageConstants.VALID_TOKEN + username));
}else {
return new ResponseEntity(new ApiResponse(false, MessageConstants.INVALID_TOKEN),
HttpStatus.BAD_REQUEST);
}
}
}
显示用户的名字:
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping
public ResponseEntity<String> getUser(){
return new ResponseEntity<String>("Amine", HttpStatus.OK);
}
}
感谢您的帮助。