有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

使用JWT和Spring时java登录失败

我正在尝试使用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) 个答案

  1. # 1 楼答案

    “授权”标题错误:

    替换自:

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

    致:

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

    可以考虑使用HTTP框架的Spring框架常量来避免这样的问题:

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