I'm using Spring 5.1 and Spring security 4.2. I'm configured access rules using an XML file. My question is, how do I write an intercept rule (access control to a URL) based on a property in the Spring security context? That is, I have a variable
productList
in the security context that is of type java.util.ArrayList. I would like to restrict access to a URL if this list is empty or null. How do I write this? I have
<http name="defaultSecurity" security-context-repository-ref="myContextRepository"
auto-config="false" use-expressions="true" authentication-manager-ref="authenticationManager"
entry-point-ref="loginUrlAuthenticationEntryPoint">
...
<intercept-url pattern="/myurl" access="length(principal.productList) > 0" />
...
</http>
but of course, teh above
length(principal.productList) > 0
expression is completely wrong. Is there a right way to write it?
Securing the URLs The most common methods are: authenticated(): This is the URL you want to protect, and requires the user to login. permitAll(): This is used for URL's with no security applied for example css, javascript. hasRole(String role): Restrict to single role.
Description. hasRole([role]) Returns true if the current principal has the specified role. hasAnyRole([role1,role2]) Returns true if the current principal has any of the supplied roles (given as a comma-separated list of strings)
Most web applications using Spring Security only have a couple of intercept-url s because they only have very basic security requirements. You need to have unauthenticated access to the login and login-error screens and usually some aspect of the public site, so that can be a few URL patterns.
By default, Spring Security uses a thread-local copy of this class. This means each request in our application has its security context that contains details of the user making the request. To use it, we simply call the static methods in SecurityContextHolder: Authentication auth = SecurityContextHolder.
Security related expressions have quite limited set of operations in Spring. You can extend this set by providing custom implementation of org.springframework.security.access.expression.SecurityExpressionOperations
interface. Here is a brief guide how to do it:
SecurityExpressionOperations
and implement desired operations:class MySecurityExpressionOperations implements SecurityExpressionOperations {
private SecurityExpressionOperations delegate;
public MySecurityExpressionOperations(SecurityExpressionOperations delegate) {
this.delegate = delegate;
}
public boolean hasProducts() {
MyUser user = (MyUser) delegate.getAuthentication().getPrincipal();
return !user.getProductList().isEmpty();
}
// Other methods
}
org.springframework.security.web.access.expression.WebExpressionVoter
and replace standard expression handler:class MyWebExpressionVoter extends WebExpressionVoter {
public MyWebExpressionVoter() {
setExpressionHandler(new DefaultWebSecurityExpressionHandler() {
@Override
protected SecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, FilterInvocation fi) {
SecurityExpressionOperations delegate = super.createSecurityExpressionRoot(authentication, fi);
return new MySecurityExpressionOperations(delegate);
}
});
}
}
<bean id="affirmativeBased" class="org.springframework.security.access.vote.AffirmativeBased">
<constructor-arg>
<list>
<bean class="my.company.MyWebExpressionVoter"/>
</list>
</constructor-arg>
</bean>
<http pattern="/**" use-expressions="true" access-decision-manager-ref="affirmativeBased">
<!-- ... -->
</http>
<intercept-url pattern="/products" access="hasProducts()"/>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With