如何在Spring Boot中在JWT内发送Authenticated用户ID?

时间:2018-05-17 12:09:40

标签: java spring-boot java-ee jwt angular5

我正在开发一个简单的应用程序使用Spring引导作为后端,Angular5作为前端,我使用Spring安全性和JWT来验证用户等。

我现在需要在angular5中获取经过身份验证的用户ID,因此我需要在将其发送到前端之前将其存储在JWT令牌中。

这是spring boot中成功验证的方法:

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

        User springUser = (User)authResult.getPrincipal();
        String jwt = Jwts.builder()
        .setSubject(springUser.getUsername())
                .setExpiration(new Date(System.currentTimeMillis()+SecurityConstants.EXPIRATION_TIME))
                .signWith(SignatureAlgorithm.HS256,SecurityConstants.SECRET)
                .claim("roles",springUser.getAuthorities())
                .compact();

     AppUser app = userRepo.findByUsername(springUser.getUsername());
     Long id = app.getId();

    ObjectMapper objectMapper = new ObjectMapper();
    JsonNode jsonJwt = objectMapper.readTree(jwt);
    ((ObjectNode)jsonJwt).put("userId", id);

     System.out.println("this ! "+jsonJwt);


response.addHeader(SecurityConstants.HEADER_STRING,SecurityConstants.TOKEN_PREFIX+objectMapper.writeValueAsString(jsonJwt));

                   }

关于如何做到这一点的任何想法?任何有用的链接?

提前谢谢。

修改

JWTAuthorizationFilter.java类

    package interv.Web.service;

import interv.Web.security.SecurityConstants;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;

public class JWTAutorizationFilter extends OncePerRequestFilter{


    @Override
    protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {


        httpServletResponse.addHeader("Access-Control-Allow-Origin","*");
        httpServletResponse.addHeader("Access-Control-Allow-Headers", " Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers, Authorization");
        httpServletResponse.addHeader("Access-Control-Expose-Headers",
                "Access-Control-Allow-Origin, Access-Control-Allow-Credentials,Authorization");
        httpServletResponse.addHeader("Access-Control-Allow-Methods","GET,PUT,POST,DELETE");


        String jwtToken = httpServletRequest.getHeader(SecurityConstants.HEADER_STRING);

         if(httpServletRequest.getMethod().equals("OPTIONS")){
             httpServletResponse.setStatus(httpServletResponse.SC_OK);
        }
         else {
             if(jwtToken==null || !jwtToken.startsWith(SecurityConstants.TOKEN_PREFIX)){

                filterChain.doFilter(httpServletRequest,httpServletResponse);

                 return ;
             }

             Claims claims = Jwts.parser()
                    .setSigningKey(SecurityConstants.SECRET)
                    .parseClaimsJws(jwtToken.replace(SecurityConstants.TOKEN_PREFIX,""))
                    .getBody();

            String username = claims.getSubject();
            ArrayList<Map<String,String>> roles = (ArrayList<Map<String,String>>)claims.get("roles");


            Collection<GrantedAuthority> authorities = new ArrayList<>();
            roles.forEach(r->{
                authorities.add(new SimpleGrantedAuthority(r.get("authority")));
             });

            UsernamePasswordAuthenticationToken authenticationToken=
                    new UsernamePasswordAuthenticationToken(username,null,authorities);
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
            filterChain.doFilter(httpServletRequest,httpServletResponse);
         }

        }

    }

我得到的错误:

ARC扩展中的

 {
"timestamp": 1526658417940,
"status": 500,
"error": "Internal Server Error",
"exception": "com.fasterxml.jackson.core.JsonParseException",
"message": "Unrecognized token 'eyJhbGciOiJIUzI1NiJ9': was expecting ('true', 'false' or 'null') at [Source: eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImV4cCI6MTUyNzUyMjQxNywicm9sZXMiOlt7ImF1dGhvcml0eSI6IkFETUlOIn1dfQ.BtaWfqSy9xyDdZrEsJD6iJRVLyTpHEVGYL1NVR670Ts; line: 1, column: 21]",
"path": "/login"
}

在控制台中:

    ERROR 4980 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception

com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'eyJhbGciOiJIUzI1NiJ9': was expecting ('true', 'false' or 'null')
 at [Source: eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsImV4cCI6MTUyNzUyMjQxNywicm9sZXMiOlt7ImF1dGhvcml0eSI6IkFETUlOIn1dfQ.BtaWfqSy9xyDdZrEsJD6iJRVLyTpHEVGYL1NVR670Ts; line: 1, column: 21]
    at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1702) ~[jackson-core-2.8.10.jar:2.8.10]
    at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:558) ~[jackson-core-2.8.10.jar:2.8.10]
    at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._reportInvalidToken(ReaderBasedJsonParser.java:2839) ~[jackson-core-2.8.10.jar:2.8.10]
    at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._handleOddValue(ReaderBasedJsonParser.java:1903) ~[jackson-core-2.8.10.jar:2.8.10]
    at com.fasterxml.jackson.core.json.ReaderBasedJsonParser.nextToken(ReaderBasedJsonParser.java:749) ~[jackson-core-2.8.10.jar:2.8.10]
    at com.fasterxml.jackson.databind.ObjectMapper._initForReading(ObjectMapper.java:3850) ~[jackson-databind-2.8.10.jar:2.8.10]
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3799) ~[jackson-databind-2.8.10.jar:2.8.10]
    at com.fasterxml.jackson.databind.ObjectMapper.readTree(ObjectMapper.java:2397) ~[jackson-databind-2.8.10.jar:2.8.10]
    at interv.Web.security.JWTAuthenticationFilter.successfulAuthentication(JWTAuthenticationFilter.java:83) ~[classes/:na]
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:240) ~[spring-security-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
    at interv.Web.service.JWTAutorizationFilter.doFilterInternal(JWTAutorizationFilter.java:43) ~[classes/:na]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.14.RELEASE.jar:4.3.14.RELEASE]

1 个答案:

答案 0 :(得分:0)

您可以使用Jackson手动操作jwt:

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

    User springUser = (User)authResult.getPrincipal();
    String jwt = Jwts.builder()
    .setSubject(springUser.getUsername())
            .setExpiration(new Date(System.currentTimeMillis()+SecurityConstants.EXPIRATION_TIME))
            .signWith(SignatureAlgorithm.HS256,SecurityConstants.SECRET)
            .claim("roles",springUser.getAuthorities())
            .compact();
   ObjectMapper objectMapper = new ObjectMapper();
   JsonNode jsonJwt = objectMapper.readTree(jwt);
   ((ObjectNode)jsonNode).put("userId", getUserId(springUser));

   response.addHeader(SecurityConstants.HEADER_STRING,SecurityConstants.TOKEN_PREFIX+objectMapper.writeValueAsString(jsonJwt));       

}