Reputation: 1458
My use case is to authenticate & then authorize users based on @PathVariable parameters. I need to execute some custom code to authorize the principal. I'm not sure of the approach to take here -
I have implemented a custom AbstractAuthenticationProcessingFilter & AuthenticationProvider for authentication, which ends up granting roles to the principal. I can inspect the pathvariables in the servlet request (using HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE), and add additional authorities to the Authentication token. Then I can use the built-in hasRole, hasPermission expressions to implement access control.
I can extend WebSecurityExpressionRoot and implement a custom AbstractSecurityExpressionHandler and define my own expressions to be used in the intercept-url access-control expressions. I'm not sure how I can access the @PathVariables when defining custom methods in my WebSecurityExpressionRoot implementation.
Which approach is preferable, or is there another way to do this cleanly?
Upvotes: 8
Views: 14022
Reputation: 121
I do have a solution. In a configuration class
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter
I could have method
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/student/{id}/**")
.access("@guard.checkUserId(authentication,#id)");
}
while @guard in SpEL links to
@Component
public class Guard {
@Autowired
private UserRepository repo;
public boolean checkUserId(Authentication authentication, int id) {
String name = authentication.getName();
System.out.println(name+" at "+id);
User result = repo.findByUsername(name);
return result != null && result.getPid() == id;
}
}
In practice, the #id in SpEL can get the value extracted from {id} in the previous line. You can do whatever you want in checkUserId, and the return value decides whether the access to the path would be allowed.
Upvotes: 12
Reputation: 8955
A way I could imagine for this would be to capture the path variable in a parameter, using method level authorization, and then using hasPermission
. This answer has details about how to do it exactly - in case it would help.
Upvotes: 1