如何使用 Spring Boot jwt 将身份验证系统连接到 React.js

Posted

技术标签:

【中文标题】如何使用 Spring Boot jwt 将身份验证系统连接到 React.js【英文标题】:How to connect authentication system with spring boot jwt to React.js 【发布时间】:2021-04-07 20:54:32 【问题描述】:

我创建了一个用 JAVA 和 spring 在服务器端编写的全栈系统,用 react.js 创建一个客户端 我制作了一个 JWT 系统,以便连接到系统并注册。 系统在服务器端工作,我想把它统一到适当的组件中 由于某种原因没有任何效果,重要的是要强调我是 react.js 的新手,这是我使用 react.js 创建的第一个项目

这是 login.jsx 组件:

    import React,  Component  from 'react'
import AuthService from '../services/AuthService';
import "./Login.css";

class login extends Component
    constructor(props)
        super(props);
        this.state=
            username: '',
           password: '',
        
        this.signin = this.signin.bind(this);
    

    signin()
        let loginRequest = username: this.state.username, password: this.state.password;

        AuthService.signin(loginRequest).then(res=>
            this.props.history.push('/home');
        );
                console.log('employee => ' + JSON.stringify(loginRequest));

    

    changeUserNameHandler= (event) => 
                this.setState(username: event.target.value);
            
            
     changePasswordHandler= (event) => 
                 this.setState(password: event.target.value);
            

    render() 
        return (
          <section className="container">
            <div className="row">
              <div className="col-md-6">
                <div className="card">
                  <form className="box">
                    <h1>Login</h1>
                    <p className="text-muted"> Please enter your User Name and Password!</p>                  
                            <input onChange=this.changeUsertNameHandler autoComplete="off" type="text" name="username" placeholder="Username"/>                        
                             <input onChange=this.changePasswordHandler autoComplete="off" type="password" name="password" placeholder="Password"/> 
                     
                          <a className="forgot text-muted" href="#">Forgot password?</a>
                          <input onClick=this.signin type="submit" name="" value="Login" href="#"/>
                      <div className="col-md-12">
                        <ul className="social-network social-circle">
                            <li><a href="#" className="icoFacebook" title="Facebook"><i className="fab fa-facebook-f"></i></a></li>
                            <li><a href="#" className="icoGoogle" title="Google +"><i className="fab fa-google-plus"></i></a></li>
                        </ul>
                    </div>

                      <div className="form-group">
                          <div className="custom-control custom-checkbox">
                          </div>
                      </div>
                      
                  </form>
            </div>
        </div>
    </div>
</section>
        );
    

export default login;

这是 AuthController(java spring):

package com.example.coffeedemo.Controller;

import com.example.coffeedemo.model.ERole;
import com.example.coffeedemo.model.Role;
import com.example.coffeedemo.model.User;
import com.example.coffeedemo.repository.RoleRepository;
import com.example.coffeedemo.repository.UserRepository;
import com.example.coffeedemo.requests.LoginRequest;
import com.example.coffeedemo.requests.SignupRequest;
import com.example.coffeedemo.response.JwtResponse;
import com.example.coffeedemo.response.MessageResponse;
import com.example.coffeedemo.security.JwtUtils;
import com.example.coffeedemo.service.UserDetailsImpl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@CrossOrigin(origins = "*", maxAge = 3600)
@RestController
@RequestMapping("/api/")
public class AuthController 

    @Autowired
    AuthenticationManager authenticationManager;

    @Autowired
    UserRepository userRepository;

    @Autowired
    RoleRepository roleRepository;

    @Autowired
    PasswordEncoder encoder;

    @Autowired
    JwtUtils jwtUtils;

    @PostMapping("/signin")
    public ResponseEntity<?> authenticateUser(@RequestBody LoginRequest loginRequest) 
        System.out.println(userRepository.findByUsername(loginRequest.getUsername()));

        Authentication authentication = authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()));

        SecurityContextHolder.getContext().setAuthentication(authentication);
        String jwt = jwtUtils.generateJwtToken(authentication);
        
        UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal();
        List<String> roles = userDetails.getAuthorities().stream()
                .map(item -> item.getAuthority())
                .collect(Collectors.toList());
        return ResponseEntity.ok(new JwtResponse(jwt,
                                                 userDetails.getId(), 
                                                 userDetails.getUsername(), 
                                                 userDetails.getEmail(), 
                                                 roles));
    
    

    @PostMapping("/signup")
    public ResponseEntity<?> registerUser(@RequestBody SignupRequest signUpRequest) 
        if (userRepository.existsByUsername(signUpRequest.getUsername())) 
            return ResponseEntity
                    .badRequest()
                    .body(new MessageResponse("Error: Username is already taken!"));
        

        if (userRepository.existsByEmail(signUpRequest.getEmail())) 
            return ResponseEntity
                    .badRequest()
                    .body(new MessageResponse("Error: Email is already in use!"));
        

        // Create new user's account
        User user = new User(signUpRequest.getUsername(),
                             signUpRequest.getEmail(),
                             encoder.encode(signUpRequest.getPassword()));

        Set<String> strRoles = signUpRequest.getRole();
        System.out.println(strRoles);
        Set<Role> roles = new HashSet<>();

        if (strRoles == null) 
            Role userRole = roleRepository.findByName(ERole.ROLE_USER)
                    .orElseThrow(() -> new RuntimeException("Error: Role is not found."));
            roles.add(userRole);
         else 
            strRoles.forEach(role -> 
                switch (role) 
                case "admin":
                    Role adminRole = roleRepository.findByName(ERole.ROLE_ADMIN)
                            .orElseThrow(() -> new RuntimeException("Error: Role is not found."));
                    roles.add(adminRole);

                    break;
                case "mod":
                    Role modRole = roleRepository.findByName(ERole.ROLE_MODERATOR)
                            .orElseThrow(() -> new RuntimeException("Error: Role is not found."));
                    roles.add(modRole);

                    break;
                default:
                    Role userRole = roleRepository.findByName(ERole.ROLE_USER)
                            .orElseThrow(() -> new RuntimeException("Error: Role is not found."));
                    roles.add(userRole);
                
            );
        

        user.setRoles(roles);
        userRepository.save(user);

        return ResponseEntity.ok(new MessageResponse("User registered successfully!"));
    

在当前情况下,当我尝试连接时,没有任何反应.. 甚至打印到 console.log..

不胜感激 谢谢!!

【问题讨论】:

【参考方案1】:

将您的input 更改为普通的&lt;button onClick=this.signin&gt;Login&lt;/button&gt;

编辑,如果没有帮助,请向我们展示您的 AuthService.signin 函数

【讨论】:

嗨,谢谢你的帮助,但我得到了 401(我相信它连接到 spring secutiry “未经授权的错误:需要完全身份验证才能访问此资源”(来自服务器) 您是否在尝试登录时得到它?如果是这样,请确保您没有在 SecurityConfig 中保护“/api/signin”端点。

以上是关于如何使用 Spring Boot jwt 将身份验证系统连接到 React.js的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot with Spring Boot:将基本身份验证与JWT令牌身份验证相结合[复制]

如何在 Spring Boot 中实现 oAuth2 和 JWT 身份验证? [关闭]

在 Spring Boot 中使用 JWT 进行简单的身份验证

使用 Spring Boot 进行 JWT 身份验证

Spring Boot JWT 身份验证

如何从 Spring Boot 应用程序调用外部 JWT API 服务 [关闭]