我有一个受 Spring Security 保护的 Spring Boot 应用程序服务器。用户首次登录时会使用用户名和密码进行身份验证。如果我使用 Spring MVC(同源),则每次调用 API 时都不必重新登录。但是,当我从 Angular 应用程序(跨源)调用 API 时,每次刷新页面时都必须提供授权。
是否可以保留我的登录 session ,而不必每次刷新页面时都发送身份验证?我是否需要某种 HTTP 拦截器服务来手动检查 Spring 服务器的响应?
我尝试调用的 REST API
@CrossOrigin(origins = "http://localhost:4200")
@RestController
public class TestControllers {
private final AtomicLong counter = new AtomicLong();
@GetMapping("/greeting")
public MessageModel greeting (@RequestParam(value = "name", defaultValue = "World") String name) {
return new MessageModel(counter.incrementAndGet(),"Hello, " + name + "!");
}
private class MessageModel{
private long id;
private String content;
//Constructor, getter & setter
}
}
身份验证 Controller
@RestController
@RequestMapping("/api/v1")
public class BasicAuthController {
@GetMapping(path = "/basicauth")
public AuthenticationModel basicauth() {
return new AuthenticationModel("You are authenticated");
}
class AuthenticationModel {
private String message;
//Constructor, getter & setter
}
}
安全配置
@Configuration
@EnableWebSecurity(debug = true)
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and()
.authorizeRequests()
.requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
.antMatchers("/**").permitAll()
.anyRequest().authenticated()
.and()
.httpBasic();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
PasswordEncoder encoder = new BCryptPasswordEncoder();
auth.inMemoryAuthentication()
.passwordEncoder(encoder)
.withUser("user")
.password(encoder.encode("asdasd"))
.roles("USER");
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("http://localhost:4200"));
configuration.setAllowedMethods(Arrays.asList("GET","POST"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
Angular 身份验证服务
authenticationService(username: string, password: string) {
return this.http.get('http://localhost:8080/api/v1/basicauth',
{ headers: { authorization: this.createBasicAuthToken(username, password) } }).pipe(map((res) => {
this.username = username;
this.password = password;
this.registerSuccessfulLogin(username, password);
}));
}
最佳答案
您的 Angular 客户端需要一个拦截器,因此请像这样创建一个新的注入(inject):
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(private authenticationService: AuthenticationService) {}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const username = this.authenticationService.username; //get your credentials from wherever you saved them after authentification
const password = this.authenticationService.password;
if (username && password) {
request = request.clone({
setHeaders: {
Authorization: this.createBasicAuthToken(username, password),
}
});
}
return next.handle(request);
}
}
并将其添加到位于 app.module.ts
中的 providers
:
{provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true},
这会将您的身份验证数据添加到每个请求中,这样您就不必每次都登录。
关于java - 如何在不发送另一个身份验证请求的情况下保持来自跨源(CORS)Spring security的登录 session ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62368879/