网络选项卡中存在 JWT 令牌,但 JavaScript、Springboot 和 React 中的响应授权标头仍为空

问题描述 投票:0回答:1

当我使用 JWT TOKEN(“授权”)从 js 向 Spring Boot 响应发送登录请求时 JWT 令牌出现在“网络”选项卡中,但响应授权标头在 JavaScript 中保持为空 Network Tab contains JWT Token

Javascript 获取 api

import { SIGN_IN, SIGN_UP } from "./ActionType";

export const signinAction = (data) => async (dispatch) => {
    try {
        const res = await fetch("http://localhost:5050/signin", {
            method: "GET",
            headers: {
                Authorization: "Basic " + btoa(data.email + ":" + data.password),
            },

        });
        console.log(res);
        const user = await res.json();
        console.log("signin user: ", user);
        const token = res.headers.get("Authorization");
        localStorage.setItem("token", token);
        dispatch({ type: SIGN_IN, payload: token });
        console.log("signin token: ", token);
    } catch (error) {
        console.log(error);
    }
};

export const signupAction = (data) => async (dispatch) => {
    try {
        const res = await fetch("http://localhost:5050/signup", {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
            },
            body: JSON.stringify({
                email: data.email,
                name: data.name,
                userName: data.userName,
                password: data.password,
            }),
        });
        const user = await res.json();
        console.log("signup user: ", user);
        dispatch({ type: SIGN_UP, payload: user });
    } catch (error) {
        console.log(error);
    }
};

休息控制器/登录

package com.vinitpk.instagramapi.instagram.controller;

import com.vinitpk.instagramapi.instagram.exception.UserException;
import com.vinitpk.instagramapi.instagram.model.User;
import com.vinitpk.instagramapi.instagram.repository.UserRepository;
import com.vinitpk.instagramapi.instagram.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;

import java.util.Optional;

@RestController
public class AuthController {

    @Autowired
    private UserService userService;

    @Autowired
    private UserRepository userRepository;

    @PostMapping("/signup")
    public ResponseEntity<User> registerUserHandler(@RequestBody User user) throws UserException {
        User createdUser = userService.registerUser(user);
        System.out.println(createdUser.getUserName());
        return new ResponseEntity<User>(createdUser, HttpStatus.OK);
    }

    @GetMapping("/signin")
    public ResponseEntity<User> signinUserHandler(Authentication authentication ) throws BadCredentialsException {
        Optional<User> optionalUser = userRepository.findByEmail(authentication.getName());
        System.out.println(optionalUser.get());
        if(optionalUser.isPresent()){
            return new ResponseEntity<User>(optionalUser.get(),HttpStatus.OK);
        }
        throw new BadCredentialsException("Invalid User name or password");
    }

}

JWT 令牌生成器

package com.vinitpk.instagramapi.instagram.configuration;

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.crypto.SecretKey;
import java.io.IOException;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

@Component
public class JwtTokenGeneratorFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException
    {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if(authentication != null){
            SecretKey key = Keys.hmacShaKeyFor(SecurityContext.JWT_KEY.getBytes());
            String jwt = Jwts.builder()
                    .issuer("instagram")
                    .issuedAt(new Date())
                    .claim("authorities", populateAuthorities(authentication.getAuthorities()))
                    .claim("userName", authentication.getName())
                    .expiration(new Date(new Date().getTime() + (10 * 60 * 60 * 1000)))
                    .signWith(key).compact();
            response.setHeader(SecurityContext.Header, jwt);
            System.out.println(jwt);
        }
        filterChain.doFilter(request, response);
    }

    public String populateAuthorities(Collection<? extends GrantedAuthority> collection){

        Set<String> authorities = new HashSet<>();
        for(GrantedAuthority authority : collection){
            authorities.add(authority.getAuthority());
        }

        return String.join(",", authorities);
    }

    protected boolean shouldNotFilter(HttpServletRequest httpServletRequest) throws ServletException{
        return !httpServletRequest.getServletPath().equals("/signin");
    }
}

Jwt 令牌验证器

package com.vinitpk.instagramapi.instagram.configuration;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.crypto.SecretKey;
import java.io.IOException;
import java.util.List;

/**
 * @author: Vinit Kelginmane
 * @project: instagram-api-springboot
 * @Date: 12-02-2024
 */

@Component
public class JwtTokenValidationFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException
    {
        String jwt = request.getHeader(SecurityContext.Header);
        System.out.println(jwt);
        if(jwt != null){
            try{
                jwt = jwt.substring(7);
                SecretKey key = Keys.hmacShaKeyFor(SecurityContext.JWT_KEY.getBytes());
                Claims claims = Jwts.parser().verifyWith(key).build().parseSignedClaims(jwt).getPayload();
                String userName = String.valueOf(claims.get("userName"));
                String authorities = (String)claims.get("authorities");
                List<GrantedAuthority> auths = AuthorityUtils.commaSeparatedStringToAuthorityList(authorities);
                Authentication token = new UsernamePasswordAuthenticationToken(userName, null, auths);
                SecurityContextHolder.getContext().setAuthentication(token);
            }
            catch (Exception e){
                throw new BadCredentialsException("Invalid Token");
            }
        }
        filterChain.doFilter(request, response);


    }

    protected boolean shouldNotFilter(HttpServletRequest httpServletRequest) throws ServletException{
        return httpServletRequest.getServletPath().equals("/signin");
    }
}

Response Body contains data correctly

但是响应头为空

javascript reactjs spring-boot jwt
1个回答
0
投票

CorsConfiguration
中添加了
SecurityFilterChain

.cors(c-> c.configurationSource(new CorsConfigurationSource() {
                    @Override
                    public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
                        CorsConfiguration corsConfiguration = new CorsConfiguration();
                        corsConfiguration.setAllowedOrigins(Arrays.asList("http://localhost:3000"));
                        corsConfiguration.setAllowedMethods(Arrays.asList("GET", "POST","DELETE","PUT"));
                        corsConfiguration.setAllowedMethods(Collections.singletonList("*"));
                        corsConfiguration.setAllowCredentials(true);
                        corsConfiguration.setAllowedHeaders(Collections.singletonList("*"));
                        corsConfiguration.setExposedHeaders(Arrays.asList("Authorization"));
                        return corsConfiguration;
                    }
                }))
© www.soinside.com 2019 - 2024. All rights reserved.