我想用spring实现自己的身份验证。为了简单起见,我将在没有任何会话的情况下实现第一步,但在每个请求中都会发送HTTP-Authorization标头。
我已经阅读了文档,很多教程,当然还在stackoverflow上进行了搜索,但我无法修复它。
我所拥有的是一个过滤器(RequestFilter
),它提取Authorization标头并使用自己的身份验证(AuthenticationToken
)初始化安全上下文。然后有一个AuthenticationProvider
(TokenAuthenticationProvider
)支持我的AuthenticationToken
。过滤器正在运行,身份验证提供程序不是。 TokenAuthenticationProvider
中没有调用任何方法。你能帮助我吗,谢谢:)。
@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private static final Logger LOGGER = Logger.getLogger(SecurityConfig.class.getName());
@Autowired
TokenAuthenticationProvider tokenAuthenticationProvider;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(new RequestFilter(), BasicAuthenticationFilter.class)
.csrf().disable()
;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.authenticationProvider(tokenAuthenticationProvider)
;
}
}
@Component
public class TokenAuthenticationProvider implements AuthenticationProvider {
private static final Logger LOGGER = Logger.getLogger(TokenAuthenticationProvider.class.getName());
@Autowired
ClientRepository clientRepository;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
final String authToken = authentication.getCredentials().toString();
LOGGER.severe("AUTH TOKEN: " + authToken);
return Optional.ofNullable(clientRepository.findByAuthToken(authToken))
.map((Client client) -> new AuthenticationToken(client.getId(), client.getAuthToken()))
.orElseThrow(() -> new AccessDeniedException(""));
}
@Override
public boolean supports(Class<?> authentication) {
LOGGER.severe(authentication.getName());
return AuthenticationToken.class.isAssignableFrom(authentication);
}
}
public class RequestFilter extends OncePerRequestFilter {
private final Logger LOGGER = Logger.getLogger(RequestFilter.class.getName());
@Override
public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
LOGGER.severe("RequestFilter works");
Optional.ofNullable(request.getHeader("Authorization"))
.ifPresent((String token) -> SecurityContextHolder
.getContext()
.setAuthentication(new AuthenticationToken(token))
);
chain.doFilter(request, response);
}
}
public class AuthenticationToken extends AbstractAuthenticationToken {
private final String credentials;
private final Long principal;
public AuthenticationToken(String credentials) {
this(null, credentials);
setAuthenticated(false);
}
public AuthenticationToken(Long principal, String credentials) {
super(null);
this.principal = principal;
this.credentials = credentials;
setAuthenticated(true);
}
@Override
public Object getCredentials() {
return credentials;
}
@Override
public Object getPrincipal() {
return principal;
}
}
@RestController
public class HttpGateController {
private static final Logger LOGGER = Logger.getLogger(HttpGateController.class.getName());
@RequestMapping(
name="/gate",
method= RequestMethod.POST,
produces = MediaType.APPLICATION_JSON_UTF8_VALUE
)
public String gateAction(@RequestBody String request) {
Optional.ofNullable(SecurityContextHolder.getContext())
.map(SecurityContext::getAuthentication)
.map(Authentication::getCredentials)
.map(ObjectUtils::nullSafeToString)
.ifPresent(LOGGER::severe);
return request;
}
@RequestMapping("/status")
public String statusAction() {
return "It works.";
}
}