使用JWT和Spring时登录失败

时间:2016-03-14 04:34:08

标签: java spring spring-mvc spring-security jwt

我正在尝试使用JWT设置身份验证,使用Angular作为我的前端,Spring作为后端。我有以下 AuthenticationFilter 类来设置JWT过滤器:

package com.atlas.config;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureException;

public class AuthenticationFilter implements Filter {

    @Override
    public void destroy() {
        // TODO Auto-generated method stub

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        //System.out.println("filter");
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;

        String authHeader = ((HttpServletRequest) request).getHeader("Authorizatoin");
        //System.out.println(authHeader);
        if (authHeader == null || !authHeader.startsWith("Bearer ")) {
            throw new ServletException("Missing or invalid Authorization header.");
        }
        String token = authHeader.substring(7);

        try
        {
            //security key needs to be changed before deployment
            Claims claims = Jwts.parser().setSigningKey("feb1atlaskey").parseClaimsJws(token).getBody();
            req.setAttribute("claims", claims);
        }
        catch(SignatureException e)
        {
            throw new ServletException("Not a valid token");
        }
        chain.doFilter(req,res);
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {
        // TODO Auto-generated method stub

    }

}

这是我的UserController类,其中登录检查和设置Auth标题发生:

package com.atlas.controller;

import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.atlas.entity.User;
import com.atlas.service.UserService;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

@RestController
@RequestMapping("/users")
public class UserController {
    private final Map<String, List<String>> userDb = new HashMap<>();

    public UserController() {
        userDb.put("tom", Arrays.asList("user"));
        userDb.put("sally", Arrays.asList("user", "admin"));
    }

    @RequestMapping(value = "login", method = RequestMethod.POST)
    public LoginResponse login(@RequestBody final UserLogin login)
        throws ServletException {
        System.out.println("In user controller");
        if (login.name == null || !userDb.containsKey(login.name)) {
            throw new ServletException("Invalid login");
        }
        return new LoginResponse(Jwts.builder().setSubject(login.name)
            .claim("roles", userDb.get(login.name)).setIssuedAt(new Date())
            .signWith(SignatureAlgorithm.HS256, "secretkey").compact());
    }


    @Autowired
    private UserService userService;

    @RequestMapping(method = RequestMethod.POST, 
            produces = MediaType.APPLICATION_JSON_VALUE, 
            consumes = MediaType.APPLICATION_JSON_VALUE)
    public void addUser(@RequestBody User u) {
        this.userService.addUser(u);
    }
        private static class UserLogin {
            public String name;
            public String password;
        }

        private static class LoginResponse {
            public String token;

            public LoginResponse(final String token) {
                this.token = token;
            }
        }
}

现在,当我使用简单表单进行登录并使用Angular发出POST请求时,它未到达UserController。它命中过滤器并将Servlet异常抛出为“丢失或无效的授权标头”。

我还配置了我的应用以在链中添加此过滤器,如下所示:

package com.atlas.config;

import javax.servlet.Filter;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class AppInit extends AbstractAnnotationConfigDispatcherServletInitializer{

    @Override
    protected Class<?>[] getRootConfigClasses() {
        // TODO Auto-generated method stub
        return new Class[]{AppConfig.class,SwaggerConfig.class,AuthenticationFilter.class};
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    protected String[] getServletMappings() {
        // TODO Auto-generated method stub
        return new String[] {"/api/*"};
    }

    @Override
    protected Filter[] getServletFilters() {
        Filter [] singleton = { new CORSFilter(), new AuthenticationFilter() };
        return singleton;
    }
}

我在这里错过了一些配置或者犯了一些可怕的错误。 任何帮助非常感谢!

1 个答案:

答案 0 :(得分:1)

“授权”标题拼写错误:

替换为:

String authHeader = ((HttpServletRequest) request).getHeader("Authorizatoin");

要:

 String authHeader = ((HttpServletRequest) request).getHeader("Authorization");

您可以考虑对http标头使用Spring Framework常量来避免此类问题:

String authHeader = ((HttpServletRequest) request).getHeader(org.springframework.http.HttpHeaders.AUTHORIZATION);