Spring REST API 控制器在使用令牌进行身份验证时重定向到主页

Spring REST API Controller is redirecting to home when authenticated with token

我的 Spring 4 应用程序上有一个 API REST 控制器 returns JSON 值,但不知何故,查看日志,调度程序将请求重定向到“/”。

2016-04-01 11:30:35 DEBUG RequestResponseBodyMethodProcessor:221 - Written [{"type":"groupmatch"}] as "application/json;charset=UTF-8" using [org.springframework.http.converter.StringHttpMessageConverter@4617ede3]
    2016-04-01 11:30:35 DEBUG DispatcherServlet:1034 - Null ModelAndView returned to DispatcherServlet with name 'dispatcher': assuming HandlerAdapter completed request handling
    2016-04-01 11:30:35 DEBUG DispatcherServlet:1000 - Successfully completed request
    2016-04-01 11:30:35 DEBUG ExceptionTranslationFilter:115 - Chain processed normally
    2016-04-01 11:30:35 DEBUG SecurityContextPersistenceFilter:97 - SecurityContextHolder now cleared, as request processing completed
    2016-04-01 11:30:35 DEBUG AntPathRequestMatcher:145 - Checking match of request : '/'; against '/'
    2016-04-01 11:30:35 DEBUG FilterChainProxy:180 - / has an empty filter list
    2016-04-01 11:30:35 DEBUG DispatcherServlet:861 - DispatcherServlet with name 'dispatcher' processing GET request for [/]
    2016-04-01 11:30:35 DEBUG RequestMappingHandlerMapping:319 - Looking up handler method for path /
    2016-04-01 11:30:35 DEBUG RequestMappingHandlerMapping:326 - Returning handler method [public java.lang.String com.thebetcafe.controllers.HomeController.home(org.springframework.web.context.request.WebRequest)]
    2016-04-01 11:30:35 DEBUG DefaultListableBeanFactory:248 - Returning cached instance of singleton bean 'homeController'
    2016-04-01 11:30:35 DEBUG DispatcherServlet:947 - Last-Modified value for [/] is: -1
    2016-04-01 11:30:35 DEBUG DispatcherServlet:1241 - Rendering view [org.springframework.web.servlet.view.JstlView: name 'static/home.html'; URL [static/home.html]] in DispatcherServlet with name 'dispatcher'
    2016-04-01 11:30:35 DEBUG JstlView:166 - Forwarding to resource [static/home.html] in InternalResourceView 'static/home.html'
    2016-04-01 11:30:35 DEBUG DispatcherServlet:861 - DispatcherServlet with name 'dispatcher' processing GET request for [/static/home.html]
    2016-04-01 11:30:35 DEBUG RequestMappingHandlerMapping:319 - Looking up handler method for path /static/home.html
    2016-04-01 11:30:35 DEBUG RequestMappingHandlerMapping:329 - Did not find handler method for [/static/home.html]
    2016-04-01 11:30:35 DEBUG SimpleUrlHandlerMapping:191 - Matching patterns for request [/static/home.html] are [/static/**]
    2016-04-01 11:30:35 DEBUG SimpleUrlHandlerMapping:220 - URI Template variables for request [/static/home.html] are {}
    2016-04-01 11:30:35 DEBUG SimpleUrlHandlerMapping:141 - Mapping [/static/home.html] to HandlerExecutionChain with handler [ResourceHttpRequestHandler [locations=[ServletContext resource [/static/]], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver@6a23a6d6]]] and 1 interceptor
    2016-04-01 11:30:35 DEBUG DispatcherServlet:947 - Last-Modified value for [/static/home.html] is: -1
    2016-04-01 11:30:35 DEBUG DispatcherServlet:1034 - Null ModelAndView returned to DispatcherServlet with name 'dispatcher': assuming HandlerAdapter completed request handling
    2016-04-01 11:30:35 DEBUG DispatcherServlet:1000 - Successfully completed request
    2016-04-01 11:30:35 DEBUG DispatcherServlet:1000 - Successfully completed request

我有一个特定的过滤功能,可以通过 header 中的令牌对用户进行身份验证,但我不确定它是如何生成的。这是代码:

    @RestController
    @RequestMapping("/api")
    public class APIController {
    ...
        @RequestMapping(value="/groups",method = RequestMethod.GET, produces = "application/json; charset=UTF-8")
            public @ResponseBody String getAllGroups(){
                List<CompetitionGroup> groups = groupService.findAllGroups();
                return groupListToJSONObject(groups);
            }
    ...
    }

dispatcher-servlet.xml

<!-- SCANNING THE COMPONENT -->
<context:component-scan base-package="com.myapp"/>
<context:annotation-config/>
<context:property-placeholder/>
<mvc:annotation-driven/>
<mvc:resources mapping="/static/**" location="/static/"/>

pom.xml

<!-- Jackson (JSON) -->
    <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-mapper-asl</artifactId>
        <version>${jackson.version}</version>
    </dependency>

我在下面为 JWT 令牌身份验证实施了一个特定的过滤器:

public class JWTTokenAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    @Autowired
    private JWTUtil jwtUtil;

    private static final Logger logger = Logger.getLogger(JWTTokenAuthenticationFilter.class);

    public JWTTokenAuthenticationFilter(){
        this("/api/");
    }

    public JWTTokenAuthenticationFilter(String defaultFilterProcessesUrl) {
        super(defaultFilterProcessesUrl);
        setAuthenticationManager(new NoOpAuthenticationManager());
        setAuthenticationSuccessHandler(new JWTSuccessAuthenticationHandler());
    }

    public final String HEADER_SECURITY_TOKEN = "Authorization";

    @Override
    protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) {
        return true;
    }


    /**
     * Attempt to authenticate request - basically just pass over to another method to authenticate request headers
     */
    @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
        String header = request.getHeader(HEADER_SECURITY_TOKEN);
        if (header == null || !header.startsWith("Bearer ")) {
            throw new JwtTokenMissingException("No JWT token found in request headers");
        }

        /* Try to parse the token */
        AppUser userDetails = jwtUtil.parseToken(header.substring(7));
        Collection<SimpleGrantedAuthority> auth = new ArrayList<>();
        auth.add(new SimpleGrantedAuthority(userDetails.getRole().name()));

        JWTAuthenticationToken token = new JWTAuthenticationToken(userDetails.getEmail(), userDetails, auth);
        token.setAuthenticated(true);

        return token;
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult)
            throws IOException, ServletException {
        super.successfulAuthentication(request, response, chain, authResult);

        // As this authentication is in HTTP header, after success we need to continue the request normally
        // and return the response as if the resource was not secured at all
        chain.doFilter(request, response);
    }

}

诀窍是 AuthenticationSuccessHandler 在验证时将请求重定向到“/”。

所以我创建了一个新的JWTSuccessAuthenticationHandler,他在身份验证后什么都不做。

public class JWTSuccessAuthenticationHandler implements AuthenticationSuccessHandler {

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
        // We do not need to do anything extra on REST authentication success, because there is no page to redirect to
    }

}

希望对某人有所帮助:)