Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I restrict access to a URL using Spring security and a property from the spring security object?

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?

like image 235
Dave Avatar asked Sep 06 '18 20:09

Dave


People also ask

How do I restrict URL in Spring Security?

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.

What is hasRole and hasAnyRole?

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)

What is intercept URL in Spring Security?

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.

How does hasRole works in Spring Security?

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.


Video Answer


1 Answers

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:

  1. Create wrapper over 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
}
  1. Extend 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);
            }
        });
    }
 }
  1. Provide custom access decision manager:
<bean id="affirmativeBased" class="org.springframework.security.access.vote.AffirmativeBased">
    <constructor-arg>
        <list>
            <bean class="my.company.MyWebExpressionVoter"/>
        </list>
    </constructor-arg>
</bean>
  1. Apply custom access decision manager:
<http pattern="/**" use-expressions="true" access-decision-manager-ref="affirmativeBased">
    <!-- ... -->
</http>
  1. Protect one of URLs with additional security operation:
<intercept-url pattern="/products" access="hasProducts()"/>
like image 57
briarheart Avatar answered Oct 06 '22 09:10

briarheart