在春季实施自己的身份验证

时间:2016-03-21 18:21:12

标签: java spring spring-security

我想用spring实现自己的身份验证。为了简单起见,我将在没有任何会话的情况下实现第一步,但在每个请求中都会发送HTTP-Authorization标头。

我已经阅读了文档,很多教程,当然还在stackoverflow上进行了搜索,但我无法修复它。

我所拥有的是一个过滤器(RequestFilter),它提取Authorization标头并使用自己的身份验证(AuthenticationToken)初始化安全上下文。然后有一个AuthenticationProviderTokenAuthenticationProvider)支持我的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.";
    }
}

0 个答案:

没有答案