我使用java springboot,jwt,spring security完成了我的项目,并且我在前端使用了react。
问题在于 de the cors,我只是无法理解,我已经编码了大约 3 个月,所以我一无所知 =(
这是我认为解决这个问题很重要的代码
import axios from "axios";
class UserService{
static BASE_URL = "http://localhost:8080"
static async login(email, password){
try{
const response = await axios.post(`${UserService.BASE_URL}/auth/login`, {email, password})
return response.data;
}catch(error){
throw error;
}
}
static async register(userData, token){
try{
const response = await axios.post(`${UserService.BASE_URL}/auth/register`, userData,
{
headers: {Authorization: `Bearer ${token}`}
})
return response.data;
}catch(error){
throw error;
}
}
/**AUTHENTICATION CHECKER */
static logout(){
localStorage.removeItem('token')
}
static isAuthenticated(){
const token = localStorage.getItem('token')
return !!token
}
}
export default UserService;
import React, { useState } from 'react';
import UserService from '../service/UserService';
import CampoTexto from '../CampoTexto';
import './FormularioCadastro.css';
export default function FormularioCadastro() {
const [formData, setFormData] = useState({
name: '',
email: '',
password: ''
});
const handleInputChange = (e) => {
const { name, value } = e.target;
setFormData({ ...formData, [name]: value });
};
const handleSubmit = async (e) => {
e.preventDefault();
try {
// Call the register method from UserService
const token = localStorage.getItem('token');
await UserService.register(formData, token);
// Clear the form fields after successful registration
setFormData({
name: '',
email: '',
password: ''
});
alert('User registered successfully');
} catch (error) {
console.error('Error registering user:', error);
alert('An error occurred while registering user');
}
};
return (
<section className="formulario-cadastro">
<div className='background-cadastro'>
<form onSubmit={handleSubmit} className='form-formulario-cadastro'>
<div className='formulario-cadastro'>
<div>
<CampoTexto type="text" name="name" value={formData.name} onChange={handleInputChange} required placeholder="Nome "/>
</div>
<div>
<CampoTexto type="email" name="email" value={formData.name} onChange={handleInputChange} required placeholder="Email" />
</div>
<div>
<CampoTexto type="password" name="password" value={formData.name} onChange={handleInputChange} required placeholder="Senha" />
</div>
</div>
<button type="submit" className='button-cadastro'>Cadastrar</button>
<a href='/auth/login' className='link-cadastrar '>Ja possui conta? Clique aqui</a>
</form>
</div>
</section>
)
}
import java.util.Arrays;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Autowired
private CustomUserDetailsService userDetailsService;
@Autowired
SecurityFilter securityFilter;
@Bean
public CorsConfigurationSource corsConfigurationSource (){
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("http://localhost:8081"));
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.cors(c -> c.configurationSource(corsConfigurationSource()))
.csrf(AbstractHttpConfigurer::disable)
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(authorize -> authorize
.requestMatchers(HttpMethod.POST, "/auth/login").permitAll()
.requestMatchers(HttpMethod.POST, "/auth/register").permitAll()
.anyRequest().authenticated()
)
.addFilterBefore(securityFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
}
@Component
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = this.userRepository.findByEmail(username).orElseThrow(() -> new UsernameNotFoundException("Usuario nao encontrado"));
return new org.springframework.security.core.userdetails.User(user.getEmail(), user.getPassword(), new ArrayList<>());
}
}
import java.util.Arrays;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Autowired
private CustomUserDetailsService userDetailsService;
@Autowired
SecurityFilter securityFilter;
@Bean
public CorsConfigurationSource corsConfigurationSource (){
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("http://localhost:8081"));
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.cors(c -> c.configurationSource(corsConfigurationSource()))
.csrf(AbstractHttpConfigurer::disable)
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(authorize -> authorize
.requestMatchers(HttpMethod.POST, "/auth/login").permitAll()
.requestMatchers(HttpMethod.POST, "/auth/register").permitAll()
.anyRequest().authenticated()
)
.addFilterBefore(securityFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
}
@Component
public class SecurityFilter extends OncePerRequestFilter {
@Autowired
TokenService tokenService;
@Autowired
UserRepository userRepository;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
var token = this.recoverToken(request);
var login = tokenService.validateToken(token);
if(login != null){
User user = userRepository.findByEmail(login).orElseThrow(() -> new RuntimeException("User Not Found"));
var authorities = Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER"));
var authentication = new UsernamePasswordAuthenticationToken(user, null, authorities);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
filterChain.doFilter(request, response);
}
private String recoverToken(HttpServletRequest request){
var authHeader = request.getHeader("Authorization");
if(authHeader == null) return null;
return authHeader.replace("Bearer ", "");
}
}
@RestController
@CrossOrigin("*")
@RequestMapping("/auth")
@RequiredArgsConstructor
public class AuthController {
private final UserRepository repository;
private final PasswordEncoder passwordEncoder;
private final TokenService tokenService;
@PostMapping("/login")
public ResponseEntity login(@RequestBody LoginRequestDTO body){
User user = this.repository.findByEmail(body.email()).orElseThrow(() -> new RuntimeException("User not found"));
if(passwordEncoder.matches(body.password(), user.getPassword())) {
String token = this.tokenService.generateToken(user);
return ResponseEntity.ok(new ResponseDTO(user.getName(), token));
}
return ResponseEntity.badRequest().build();
}
@PostMapping("/register")
public ResponseEntity register(@RequestBody RegisterRequestDTO body){
Optional<User> user = this.repository.findByEmail(body.email());
if(user.isEmpty()) {
User newUser = new User();
newUser.setPassword(passwordEncoder.encode(body.password()));
newUser.setEmail(body.email());
newUser.setName(body.name());
this.repository.save(newUser);
String token = this.tokenService.generateToken(newUser);
return ResponseEntity.ok(new ResponseDTO(newUser.getName(), token));
}
return ResponseEntity.badRequest().build();
}
}
我尝试使用浏览扩展、一些cors配置和很多其他东西
创建一个实现 WebMvcConfigurer 的类并重写以下方法:
@Configuration
//@Component
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins(
"{your_react_all_base_url}")
.allowedMethods("*")
.allowedHeaders("*")
.maxAge(3600L);
}
}
在安全过滤器链中
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.cors(Customizer.withDefault())).
// other config
}