【问题标题】:How to add the bearer token that is currently added to the response's auth header, to the response body?如何将当前添加到响应的 auth 标头的不记名令牌添加到响应正文?
【发布时间】:2021-11-18 23:00:32
【问题描述】:

我通过使用承载令牌实现了对 SpringBoot API 的授权,当登录成功时,它被添加到响应的“授权”标头中,然后需要通过我的 React 项目的登录获取方法读取这个令牌并添加到随后的请求“授权”标头。

不幸的是,尽管有人告诉我这是不可能使用 Fetch 的,所以我现在正在尝试重构我的登录功能,以便它在响应正文中返回令牌,而不是在标头中。

我不知道该怎么做,目前没有返回 JSON 正文对象,只有标题,我将不得不更改很多我的 AuthorizationFilter 和 AuthenticationFilter 类。如果有人能指出我正确的方向或建议我改变什么,我将不胜感激。

谢谢。

授权过滤器:

public class AuthorizationFilter extends BasicAuthenticationFilter {

public AuthorizationFilter(AuthenticationManager authenticationManager) { super(authenticationManager);}

protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)

        throws IOException, ServletException {

        String header = request.getHeader("Authorization");

        if(header == null || !header.startsWith("Bearer")) {

        filterChain.doFilter(request,response);

        return;
        }

        UsernamePasswordAuthenticationToken authenticationToken = getAuthentication(request);

        SecurityContextHolder.getContext().setAuthentication(authenticationToken);

        filterChain.doFilter(request,response);

        }


private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
        String token = request.getHeader("Authorization");
        if(token != null) {

        String user = Jwts.parser().setSigningKey("SecretKeyToGenJWTs".getBytes())
        .parseClaimsJws(token.replace("Bearer",""))
        .getBody()
        .getSubject();

        if(user != null) {

        return new UsernamePasswordAuthenticationToken(user, null, new ArrayList<>());

        }
        return null;
        }
        return null;
        }
}

身份验证过滤器:

   public class AuthenticationFilter extends UsernamePasswordAuthenticationFilter {

        private AuthenticationManager authenticationManager;

        public AuthenticationFilter(AuthenticationManager authenticationManager) {
            this.authenticationManager = authenticationManager;
            setFilterProcessesUrl("/login");
        }
        @Override

        public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
            try {

                com.example.gambit2.domain.User creds = new ObjectMapper().readValue(request.getInputStream(), com.example.gambit2.domain.User.class);
                return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(creds.getUsername(), creds.getPassword(),new ArrayList<>()));
            }

        catch(IOException e) {

                throw new RuntimeException("Could not read request" + e);
            }

        }
        protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain, Authentication authentication)
        {
            String token = Jwts.builder()
                    .setSubject(((User) authentication.getPrincipal()).getUsername())
                    .setExpiration(new Date(System.currentTimeMillis() + 864_000_000))
                    .signWith(SignatureAlgorithm.HS512, "SecretKeyToGenJWTs".getBytes())
                    .compact();
            response.addHeader("Authorization","Bearer " + token);


        }
    }

UserController的注册方法:

@PostMapping("/signup")
        public void signUp(@RequestBody User user) {
                user.setPassword(bCryptPasswordEncoder.encode(user.getPassword()));
                userRepository.save(user);
                System.out.println(user.getUsername() + " SAVED SUCCESSFULLY");
        }

反应 Home.js:

const SIGNUP_URL = 'http://localhost:8080/users/signup';
const LOGIN_URL = 'http://localhost:8080/login';
class Home extends Component {

    constructor(props) {
        super(props);
        this.state = {
            isAuthenticated:false,
            resData: ''
        };
    }

    componentDidMount() {
        const payload = {
            "username": "hikaru",
            "password": "JohnSmith72-"
        };
        fetch(SIGNUP_URL, {
            method: 'POST',
            headers: {
                "Accept": "application/json",
                "Content-Type": "application/json"
            },
            body: JSON.stringify(payload)
        })
            .then(response => response.json())
            .then((data) => {
                console.log(data);
            });
        fetch(LOGIN_URL, {
            method: 'POST',
            headers: {
                "Accept": "application/json",
                "Content-Type": "application/json"
            },
            body: JSON.stringify(payload)
        })
            .then(response =>

                console.log(response.headers.get("Authorization")
            );

    }

在上面的 fetch 调用中,/signup 成功,服务器输出“Tim 已成功保存”,登录也成功,但令牌作为响应发送,“console.log(response.headers.get ("Authorization")) 返回 'null'。

我知道 CORS fetch 不适用于 auth 标头,因为它只能用于类似 4 个标头,对吗?

我尝试添加一个方法,循环遍历每个条目并打印它们,然后在 .then() 中调用它:

.then(response => this.iterateThroughEntries(response)
        );

但这只打印了默认标题,而不是 auth 标题。

谢谢

【问题讨论】:

    标签: java reactjs spring spring-boot fetch


    【解决方案1】:

    我设法通过添加'localhost:8080''localhost:3000'作为源并添加授权标头作为公开来更新我的WebSecurityConfig类中的CorsSource,从而成功地从服务器接收授权标头标头,以便 CORS 请求可以使用它。

    configuration.addExposedHeader("Authorization");
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-02-17
      • 1970-01-01
      • 1970-01-01
      • 2020-03-16
      • 2016-04-13
      • 1970-01-01
      • 2016-05-15
      相关资源
      最近更新 更多