手动网络身份验证后的身份验证 websocket 会话
Auth websocket session after manual web auth
我在 SpringBoot 上使用 Spring 安全和 STOMP WebSocket。当我使用简单的登录表单时,websocket 上的 Auth 使用此配置工作正常:
@EnableWebSecurity
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/webjars/**", "/resources/**").permitAll()
.antMatchers("/register").anonymous()
.anyRequest()
.fullyAuthenticated()
.and()
.formLogin()
.loginPage("/login")
.successHandler(customLoginSuccessHandler)
.failureUrl("/login?error")
.permitAll()
.and()
.csrf().disable()
.logout().logoutSuccessHandler(customLogoutSuccessHandler);
}
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
@Override
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
messages
.nullDestMatcher().authenticated()
.simpTypeMatchers(CONNECT).authenticated()
.simpSubscribeDestMatchers(Channel.SYSTEM_ERROR.value()).permitAll()
.simpDestMatchers("/app/publish*").hasRole("USER")
.simpSubscribeDestMatchers("/user/**", "/topic/**", "/system/*").hasRole("USER")
.anyMessage().denyAll();
}
但是当我想在 RegisterController 中注册新用户后手动验证客户端时:
@RequestMapping(value = "/register", method = RequestMethod.POST)
public String signup(@Valid @ModelAttribute SignupForm signupForm, Errors errors) {
if (errors.hasErrors()) {
return SIGNUP_VIEW_NAME;
}
User user = signupForm.createAccount();
try {
userService.persist(user);
} catch (EntityExistsException ex) {
errors.rejectValue("login", "user.exists");
return SIGNUP_VIEW_NAME;
}
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(user, null, Collections.singletonList(new SimpleGrantedAuthority("USER"))));
return "redirect:/";
}
我在使用 auth websocket 时遇到问题。当我被重定向到 websocket 连接的页面时,我得到 org.springframework.security.access.AccessDeniedException: Access is denied
所以。问题出在定义角色中。在控制器中,当我定义 new SimpleGrantedAuthority("USER")
时,它应该是 "ROLE_USER"
因为 Spring 默认添加了 refix ROLLE_。当然,我们可以通过在 WebSecurity 配置中添加 next
来更改默认行为
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**", "/favicon.ico");
web.expressionHandler(new DefaultWebSecurityExpressionHandler() {
@Override
protected SecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, FilterInvocation fi) {
WebSecurityExpressionRoot root = (WebSecurityExpressionRoot) super.createSecurityExpressionRoot(authentication, fi);
root.setDefaultRolePrefix(""); //remove the prefix ROLE_
return root;
}
});
}
。是的,愚蠢的错误,但很常见。所以我会把它放在这里
我在 SpringBoot 上使用 Spring 安全和 STOMP WebSocket。当我使用简单的登录表单时,websocket 上的 Auth 使用此配置工作正常:
@EnableWebSecurity
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/webjars/**", "/resources/**").permitAll()
.antMatchers("/register").anonymous()
.anyRequest()
.fullyAuthenticated()
.and()
.formLogin()
.loginPage("/login")
.successHandler(customLoginSuccessHandler)
.failureUrl("/login?error")
.permitAll()
.and()
.csrf().disable()
.logout().logoutSuccessHandler(customLogoutSuccessHandler);
}
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
@Override
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
messages
.nullDestMatcher().authenticated()
.simpTypeMatchers(CONNECT).authenticated()
.simpSubscribeDestMatchers(Channel.SYSTEM_ERROR.value()).permitAll()
.simpDestMatchers("/app/publish*").hasRole("USER")
.simpSubscribeDestMatchers("/user/**", "/topic/**", "/system/*").hasRole("USER")
.anyMessage().denyAll();
}
但是当我想在 RegisterController 中注册新用户后手动验证客户端时:
@RequestMapping(value = "/register", method = RequestMethod.POST)
public String signup(@Valid @ModelAttribute SignupForm signupForm, Errors errors) {
if (errors.hasErrors()) {
return SIGNUP_VIEW_NAME;
}
User user = signupForm.createAccount();
try {
userService.persist(user);
} catch (EntityExistsException ex) {
errors.rejectValue("login", "user.exists");
return SIGNUP_VIEW_NAME;
}
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(user, null, Collections.singletonList(new SimpleGrantedAuthority("USER"))));
return "redirect:/";
}
我在使用 auth websocket 时遇到问题。当我被重定向到 websocket 连接的页面时,我得到 org.springframework.security.access.AccessDeniedException: Access is denied
所以。问题出在定义角色中。在控制器中,当我定义 new SimpleGrantedAuthority("USER")
时,它应该是 "ROLE_USER"
因为 Spring 默认添加了 refix ROLLE_。当然,我们可以通过在 WebSecurity 配置中添加 next
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**", "/favicon.ico");
web.expressionHandler(new DefaultWebSecurityExpressionHandler() {
@Override
protected SecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, FilterInvocation fi) {
WebSecurityExpressionRoot root = (WebSecurityExpressionRoot) super.createSecurityExpressionRoot(authentication, fi);
root.setDefaultRolePrefix(""); //remove the prefix ROLE_
return root;
}
});
}
。是的,愚蠢的错误,但很常见。所以我会把它放在这里