如何在用于生成令牌的同一过滤器中对JWT令牌进行身份验证

时间:2020-03-30 06:21:47

标签: java spring spring-boot spring-security

我正在研究Spring Security,因此在使用生成的令牌验证后续请求时遇到问题。

据我所知,一旦用户登录并生成了令牌,那么对于每个后续请求,我应该如何验证令牌。

基本上,我的意思是在下面的类中,它已经成功生成了令牌,并且在响应中添加了cookie,仅用于测试目的。请看下面的课。

package com.example.demo;

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

public class AuthenticationFilter extends UsernamePasswordAuthenticationFilter {

    private AuthenticationManager authenticationManager;

    private static final Logger log=Logger.getAnonymousLogger();

    public AuthenticationFilter(AuthenticationManager autheticationManager) {
        this.setAuthenticationManager(autheticationManager);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException {

        /*
         * List list = new ArrayList<GrantedAuthority>(); GrantedAuthority auth = ()-> {
         * return "USER"; };
         * 
         * list.add(auth.getAuthority());
         */
        return getAuthenticationManager().authenticate(
                new UsernamePasswordAuthenticationToken("user", "password"));
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
            Authentication authResult) throws IOException, ServletException {
        response.addHeader("Token", "Logged in");
        HttpSession session = request.getSession();
        Cookie cookies = new Cookie("token", "True");
        cookies.setMaxAge(60);
        session.setAttribute("cookie", cookies);
        log.log(Level.INFO, "Authentication Successull Cookies has been added to the session Context");
    }

}

现在,如果我没有记错的话,进一步的请求将必须通过doFilterInternal方法。好的,因此从这里我可以验证令牌以对请求进行身份验证,并确定是否必须通过。为了重写此方法,我将需要扩展OncePerRequestFilter或BasicAuthenitcation类,但是在Java中,我们受到限制,只能扩展一个类。

如果我们正在考虑实现一个接口,并且可以在该接口中实现该类,那么这也是不可能的,因为所需的类是抽象的,因此不可能在接口中实现它们。

如果我们要创建另一个类来使用doFilterInternal方法实现这些类,则必须将其作为过滤器添加到WebSecurityConfig类中,但众所周知,它只能添加一个过滤器。

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
        http.authorizeRequests().antMatchers("/**")
        .hasRole("USER").and().formLogin()
        .and().addFilter(getAuthenticationFilter());
    }

所以我很困惑此时该做什么。请提出一些建议。

1 个答案:

答案 0 :(得分:0)

我设法解决了这个问题,我们可以在不涉及任何其他API的同一类中生成令牌并对其进行验证,因为如果您使用的是微服务体系结构,那么您将不得不陷入混乱。

所以我要做的是,在下面创建了一个自定义Filter类。

AutheticationFilter.class

package com.example.demo;

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

public class AuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    private static final Logger log=Logger.getAnonymousLogger();

    protected AuthenticationFilter(AuthenticationManager authenticationManager) {
        super(new AntPathRequestMatcher("/login", "POST"));
        this.setAuthenticationManager(authenticationManager);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException {

        String user = request.getParameter("username");
        String password = request.getParameter("password");
        log.log(Level.INFO, "Username from the Request: "+user);
        log.log(Level.INFO, "Password from the request: "+password);

        /*
         * List list = new ArrayList<GrantedAuthority>(); GrantedAuthority auth = ()-> {
         * return "USER"; };
         * 
         * list.add(auth.getAuthority());
         */
        return getAuthenticationManager().authenticate(
                new UsernamePasswordAuthenticationToken("user", "password"));
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        System.out.println("Do filter authentication filter invoked");
        super.doFilter(req, res, chain);
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
            Authentication authResult) throws IOException, ServletException {
        System.out.println("Authentication Successull Cookies has been added to the session Context");
        response.addHeader("Token", "Logged in");
        HttpSession session = request.getSession();
        Cookie cookies = new Cookie("token", "True");
        cookies.setMaxAge(60);
        session.setAttribute("cookie", cookies);
        log.log(Level.INFO, "Authentication Successull Cookies has been added to the session Context");
    }

}

使用Http Security方法之前的添加过滤器将此过滤器添加到配置类中。