我的 React 应用程序只是一个简单的登录页面,我的目的是如何通过 React Login 处理 Spring Security 身份验证,
我的 React 应用程序正在本地主机上运行:5713
我的 Spring 应用程序正在 localhost:5001 运行
我的反应代码:
export default function Login(){
let [username,setUsername]=useState('')
let [password,setPassword]=useState('')
let formSubmit=async(e)=>{
e.preventDefault();
console.log(username,password)
const login=await fetch("http://localhost:5001/login",{
method: 'POST',
headers:{
'Content-Type':'application/json'
},
body:JSON.stringify({username,password})
})
console.log(login)
const data=login.json();
console.log(data)
}
// useEffect(()=>{
// },[])
return(
<>
<form onSubmit={formSubmit}>
<label htmlFor="username">Name</label>
<input id="username" name="username" type="text" value={username} onChange={e=>setUsername(e.target.value)} />
<label htmlFor="password">Password</label>
<input id="password" name="password" value={password} onChange={e=>setPassword(e.target.value)} type="password" />
{/* <button type="submit">Login</button> */}
<Button>Submit</Button> <!-- my custom button Component -->
</form>
</>
)
}
这是我的 Spring Boot Security 的样子:
@EnableWebSecurity
public class SecurityConfigTest implements WebMvcConfigurer {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.securityMatcher("/**")
.authorizeHttpRequests(authorize -> authorize
.requestMatchers("/user/add", "/csrf", "/login").permitAll()
.anyRequest().authenticated()
)
.formLogin(formLogin -> formLogin
.loginPage("http://localhost:5173/login") // My react app Login Form
.defaultSuccessURL("/testing") //its defined in my Springboot controller
)
return http.build();
}
@Bean
UserDetailsService userDetailsService(PasswordEncoder pa) {
UserDetails user=User.withUsername("admin")
.password(pa.encode("pass"))
.roles("ADMIN")
.build();
System.out.println("at userDetailsService");
UserDetails user1=User.withUsername("user")
.password(pa.encode("user"))
.roles("USER")
.build();
System.out.println(user.getUsername());
System.out.println(user.getPassword());
return new InMemoryUserDetailsManager(user,user1);
}
}
我在我的控制器类级别使用 @CrossOrigin(origins = "http://localhost:5173") 到我的 Spring Boot 应用程序中。
我的控制器:
@Controller
@CrossOrigin(origins = "http://localhost:5173")
class ConnTest{
UserRepo userRepo;
@Autowired
TestingSerivce test;
// one way to read the app.props values
@Value("${spring.jpa.database}")
String dbname;
ConnTest(UserRepo userRepo,TestingSerivce test){
this.userRepo=userRepo;
this.test=test;
}
@ResponseBody
@GetMapping("/")
String test(HttpServletRequest req) {
return "Hello Welcome to my Demo";
}
@ResponseBody
@PostMapping("/user/add")
int addUser(@RequestBody User user) {
userRepo.save(user);
System.out.println(user);
return 1;
}
@ResponseBody
@GetMapping("/out")
String logoutHere(HttpServletRequest req) throws ServletException {
System.out.println(req.getRemoteUser()+"\nSession : "+req.getSession());
req.logout();
HttpSession session = req.getSession(false);
if(session!=null) session.invalidate();
System.out.println(req.getRemoteUser()+"\nSession : "+req.getSession());
return "Logging out...";
}
@ResponseBody
@GetMapping("/csrf")
CsrfToken httpServReq(HttpServletRequest req) {
// return securityConfig.csrfToken(req);
System.out.println("tesing");
return (CsrfToken) req.getAttribute("_csrf");
}
@ResponseBody
@GetMapping("/test/x")
String testx(@RequestParam(required = false) String msg) {
String header="{'ab':'xyx'}";
byte []b=header.getBytes();
String encoded=Base64.getEncoder().encodeToString(b);
System.out.println(encoded);
if (msg == null) {
return "Null Msg";
}
return "this is my Testingx -> " + msg;
}
@ResponseBody
@PostMapping("/login")
UserDetails userLogin(@RequestBody UserDetail user) {
System.out.println(user.getUsername()+" -- "+user.getPassword());
return user;
}
}
问题:
每当我尝试访问 Spring Controller 中定义的任何安全路由(不要像这样使用它一样好)时,我都会成功获取 React 登录表单,但每当我提供凭据并点击“提交”按钮时,我都会得到Cors 错误,即使我在控制器类级别提到过它。
也无法重定向到 secureRoutes
当我对不安全的 URL 进行相同的尝试时,Cors 工作得很好,没有任何问题。所以我相信只有在使用安全路线时才会出现问题。
我在使用Spring Security Authentication时有什么错误吗?
Access to fetch at 'http://localhost:5001/login' from origin 'http://localhost:5173' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Login.jsx:14
POST http://localhost:5001/login net::ERR_FAILED
formSubmit @ Login.jsx:14
callCallback2 @ react-dom.development.js:4164
invokeGuardedCallbackDev @ react-dom.development.js:4213
invokeGuardedCallback @ react-dom.development.js:4277
invokeGuardedCallbackAndCatchFirstError @ react-dom.development.js:4291
executeDispatch @ react-dom.development.js:9041
processDispatchQueueItemsInOrder @ react-dom.development.js:9073
processDispatchQueue @ react-dom.development.js:9086
dispatchEventsForPlugins @ react-dom.development.js:9097
(anonymous) @ react-dom.development.js:9288
batchedUpdates$1 @ react-dom.development.js:26179
batchedUpdates @ react-dom.development.js:3991
dispatchEventForPluginEventSystem @ react-dom.development.js:9287
dispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay @ react-dom.development.js:6465
dispatchEvent @ react-dom.development.js:6457
dispatchDiscreteEvent @ react-dom.development.js:6430
Show 15 more frames
Show less
Login.jsx:14
Uncaught (in promise) TypeError: Failed to fetch
at formSubmit (Login.jsx:14:27)
at HTMLUnknownElement.callCallback2
您必须在 Springboot 应用程序中启用
CORS policy
。您可以使用以下方法来做到这一点:-
@CrossOrigin
public class ConnTest {
}
请参阅此答案以获取更多上下文: - 起源已被 CORS 策略 Spring boot 和 React 阻止