所以我有一个Angular前端应用程序和一个Spring后端应用程序。目前,我的应用程序上似乎有一个JSessionId的cookie(我只在登录时收到,而不是在注册时收到,无论出于什么原因)(cookies)
我假设它会将这些cookie发送回服务器。(尽管这只是一个假设)
现在,当我向受保护的服务器发出请求时,得到的唯一结果是弹出“请登录”。Login popup
当我登录时,我的UserService记录了一个用户,其中包含以下详细信息:
UsernamePasswordAuthenticationToken [Principal=User(userId=1, name=Maksym Riabov, username=MRiabov, password={bcrypt}$2a$10$W0XJRQdfxV5XXORkr2bTluIHvFetIVBzmVp51l39T5zLCQk12RV1i, company=null, enabled=true), Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=null], Granted Authorities=[ADMIN]]
我注意到这里的sessionId是空的,为什么会这样呢?
为了回答前面的一些问题:
- 是的,我已粘贴{withCredentials:true}到每个请求。(特定于Angular )
- 是的,我读过文档--我甚至试着从它那里粘贴所有的代码,看起来它不起作用。
我的登录控制器:
@GetMapping("/login")
public ResponseEntity<String> login() {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
return ResponseEntity.ok("123123");
}
@PostMapping("/register")
public ResponseEntity<Map<String, String>> register(@RequestBody UserRegisterDto userDto) {
//todo check if name taken
User user = userMapper.toEntity2(userDto);
user.setPassword(passwordEncoder.encode(user.getPassword()));
user.setEnabled(true);
//todo remove
Authority authority = authorityRepository.save(new Authority("ADMIN"));
user.setAuthorities(Set.of(authority));
//todo REMOVE!!!!
User savedUser = userRepository.save(user);
System.out.println("registration works!");
return ResponseEntity.ok(Map.of("result",authority.getAuthority().getAuthority()));
}
现在,我发送一个请求到后端(它把弹出窗口以上),像这样:
@PreAuthorize("hasRole('ADMIN')")
@GetMapping("/create")
public ResponseEntity<OnboardingPathDto> createOnboardingPath() {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
// erased a bit of code here
return ResponseEntity.ok().build();
如您所见,我有一个方法安全性,它抛出auth请求。
最上面的樱桃
@Component
@EnableWebSecurity
@EnableMethodSecurity(securedEnabled = true, jsr250Enabled = true)
@RequiredArgsConstructor
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http, UserDetailsService userDetailsService) throws Exception {
http
.csrf().disable().cors().disable()
.authorizeHttpRequests()
.anyRequest().permitAll() //todo this is unsafe
.and().sessionManagement(session -> session.
sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.maximumSessions(1))//to force only one session per user
//here I tried sessionManagement to do something, but did it do something?
.rememberMe((rememberMe) -> rememberMe.userDetailsService(userDetailsService))
.httpBasic();
return http.build();
}
@Bean
public AuthenticationManager authenticationManager(DaoAuthenticationProvider daoAuthenticationProvider) throws Exception {
return new ProviderManager(daoAuthenticationProvider);
}
@Bean
public DaoAuthenticationProvider prov(PasswordEncoder passwordEncoder, UserDetailsService userDetailService) throws Exception {
DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
daoAuthenticationProvider.setPasswordEncoder(passwordEncoder);
daoAuthenticationProvider.setUserDetailsService(userDetailService);
return daoAuthenticationProvider;
}
@Bean
public PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
@Bean
public HttpSessionEventPublisher httpSessionEventPublisher() {//to force only one session per user
return new HttpSessionEventPublisher();
}
我已经广泛地阅读了Spring Security文档,甚至还参加了一门关于它的课程,但我仍然无法使它工作。
所以,我在纠结的是:
- ###为什么Spring不能通过会话进行身份验证,即使它被配置为这样做?我的错误在哪里?
编辑:我假设将会话直接发送到Angular(在REST中,而不是在cookie中)确实不安全,对吗?我目前依赖cookie。
编辑2:ffs,我受够了,我只想做oauth2认证。
1条答案
按热度按时间lf5gs5x21#
编辑:我假设将会话直接发送到Angular(在REST中,而不是在cookie中)确实不安全,对吗?我目前依赖cookie。
你说得对,这是个坏主意。对于在浏览器中运行的应用程序中的会话,只使用带有这两个标记的cookie(值=
true
):secure
(仅通过https交换)http-only
(在Javascript中隐藏)。这意味着Angular代码不应访问cookie,而是在向后端发送请求之前由浏览器自动设置cookie。
您还应该实现CSRF保护(这是spring-security中的默认设置)。
编辑2:ffs,我受够了,我只想做oauth2认证。
好主意。这对安全性、用户体验(SSO)和开发者体验都有好处:大多数OIDC提供商,无论是在内部部署(如Keycloak)还是在云中(如Auth0、Cognito等),都已经提供了登录表单(包括MultiFactorA身份验证)、用户注册、配置文件编辑、管理屏幕(如客户端声明、用户角色分配等)。
tokenRelay
过滤器的spring-cloud-gateway)将保留该会话,将令牌关联到该会话,并且在将请求转发到resource-server之前用令牌替换会话