-
Notifications
You must be signed in to change notification settings - Fork 6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WebSocket matchers ignore parameters #4469
Comments
I found a workaround. You can use implicit variable And you need extra work to be done in the service: @Component
public class WebSocketSecurity {
@Autowired
private WebSecurity webSecurity;
public boolean checkLocationByMsg(Authentication authentication, Message<?> message) {
StompHeaderAccessor sha = StompHeaderAccessor.wrap(message);
String topic = sha.getDestination();
String location = topic.replace(MyConstants.listTopicPrefix, "");
return webSecurity.checkLocation(authentication, location);
} |
Here is my (even more hackish) approach to extract the path variables: @Configuration
public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
// see https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#websocket
@Override
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
messages
.nullDestMatcher().hasRole("USER")
// BUG: Ant Style matchers do not return the value (https://github.com/spring-projects/spring-security/issues/4469)
.simpSubscribeDestMatchers(SUBSCRIBE_TO_USER_EVENTS_PATTERN)
.access("@webSecurity.checkUserCanSubscribeTo(authentication,message)")
.simpSubscribeDestMatchers("/topic/*").hasRole("USER")
.simpTypeMatchers(MESSAGE, SUBSCRIBE).denyAll()
.anyMessage().denyAll();
}
@Bean
public WebSecurity webSecurity() {
return new WebSecurity();
}
/**
* Checks that the current logged in user is allowed to subscribe based on
* paths.
*
* The path pattern "{userId}" is used to restrict access based on the current principal.
*
* E.g. the logged in user "user_a" ...
* * can subscribe to "/user/queue/accounts/user_a/events"
* * cannot subscribe to "/user/queue/accounts/user_b/events"
*
* This class is for demonstration and an ugly workaround for https://github.com/spring-projects/spring-security/issues/4469
*/
public static class WebSecurity {
final static String SUBSCRIBE_TO_USER_EVENTS_PATTERN = "/user/queue/accounts/{userId}/events";
private final static String USER_ID = "userId";
public boolean checkUserCanSubscribeTo(Authentication authentication, Message<?> message) {
final String targetedUserId = extractUserId(SUBSCRIBE_TO_USER_EVENTS_PATTERN, message);
return isAuthenticatedAndInUserRole(authentication)
&& validDestinationUserForSubscribing((User) authentication.getPrincipal(),
targetedUserId);
}
boolean validDestinationUserForSubscribing(User principal, String subscribeTo) {
return principal != null && principal.getUsername().equalsIgnoreCase(subscribeTo);
}
private boolean isAuthenticatedAndInUserRole(Authentication authentication) {
return authentication.isAuthenticated()
&& authentication.getAuthorities().stream()
.anyMatch(authority -> "ROLE_USER".equals(authority.getAuthority()));
}
private String extractUserId(String pattern, Message<?> message) {
StompHeaderAccessor sha = StompHeaderAccessor.wrap(message);
String topic = sha.getDestination();
final AntPathMatcher matcher = new AntPathMatcher("/");
if (!matcher.match(pattern, topic)){
return null;
}
final Map<String, String> uriTemplateVariables = matcher
.extractUriTemplateVariables(pattern, topic);
return uriTemplateVariables.get(USER_ID);
}
}
} |
If anyone is interested in submitting a PR I'd be happy to help get this merged in |
@rwinch I'd like to take this one |
@Daniel69 Thanks for volunteering! The issue is all yours. If have any questions or need any help, please let me know! |
@rwinch I made a PR with my first aproach to solve this issue, I'll be happy to know your opinion about my approach and to make any adjustments in the case that may be necessary. |
Extract path variables expressed in SimpDestinationMessageMatcher's pattern. Issue: spring-projectsgh-4469
Extract path variables expressed in SimpDestinationMessageMatcher's pattern. Issue: gh-4469
Fixed via gh-6110 |
Summary
I want to authorize topic subscription by topic name.
.simpSubscribeDestMatchers("/topic/list/{location}/**") .access("@webSecurity.checkLocation(authentication,#location)")
Actual Behavior
My
location
parameter is not passed towebSecurity.checkLocation()
. The method is called, but the parameter isnull
.Expected Behavior
Correct, non-null,
location
parameter passed towebSecurity.checkLocation()
method. According to the documentation this is possible for antMatchershttps://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#el-access-web-path-variables
Please suggest workarounds if exist.
Configuration
Version
compile group: 'org.springframework.security.oauth', name: 'spring-security-oauth2', version: '2.1.1.RELEASE'
compile group: 'org.springframework.security', name: 'spring-security-messaging', version: '4.2.3.RELEASE'
Sample
The text was updated successfully, but these errors were encountered: