简体   繁体   中英

Securing url pattern based on user properties Spring security

I have secured certain url patterns for my project based on the users role as seen in my spring_security xml below.

 <security:http auto-config="true" use-expressions="true" access-denied-page="/auth/denied.do" >

    <security:intercept-url pattern="/auth/login" access="permitAll"/>
    <security:intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')"/>
    <security:intercept-url pattern="/security/**" access="hasRole('ROLE_SECURITY')"/>
    <security:intercept-url pattern="/common/**" access="hasRole('ROLE_USER')"/>
    <security:intercept-url pattern="/notsecure/**" access="permitAll"/>

    <security:form-login
        login-page="/auth/login.do"
        authentication-failure-url="/auth/login.do?error=true"
        default-target-url="/common/tasks/tasks.do"
        authentication-success-handler-ref="mySuccessHandler"/>

    <security:logout
        invalidate-session="true"
        logout-success-url="/auth/login.do"
        logout-url="/auth/logout.do"/>

</security:http>
<sec:global-method-security pre-post-annotations="enabled" />

<!-- Declare an authentication-manager to use a custom userDetailsService -->
<security:authentication-manager>
    <security:authentication-provider user-service-ref="authenticationService">
        <!--   <security:password-encoder ref="passwordEncoder"/> -->
    </security:authentication-provider> 
</security:authentication-manager>

<!-- Use a Md5 encoder since the user's passwords are stored as Md5 in the database -->
<!--
<bean class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" id="passwordEncoder"/>
-->

<!-- A custom service where Spring will retrieve users and their corresponding access levels  -->
<bean id="authenticationService" class="ie.premiumpower.services.AuthenticationService"/>
<bean id="mySuccessHandler" class="ie.premiumpower.services.MySuccessHandler">
</bean>

So only admin users can access /admin/** etc.

Now I want to limit users to their own url pattern based on a different attribute (their site_id which is just an int). So only users with a site_id of 1 can go to the url "/1/**" and so on.

How can I go about doing this? Just looking for a point in the right direction. Everything I've seen so far doesn't allow me to have a variable url-pattern. As in "/{variable}/".

https://docs.spring.io/spring-security/site/docs/3.0.x/reference/el-access.html

See "15.3 Method Security Expressions"

You can use something like

@PreAuthorize("#value == '123'")
@RequestMapping(value="/secure")
@ResponseBody
public String aloa(@RequestParam("value") String value, Principal principal) {
        return "Hello " + principal.getName();
}

This will only let you in if you provide "value=123" as a request Parameter.

You may also use @PathVariable here:

@PreAuthorize("#value == '123'")
@RequestMapping(value="/secure/{value}/data")
@ResponseBody
public String aloa(@PathVariable("value") String value, Principal principal)

If you want fine-grain access control to your domain objects, you may want to use spring-acl for such purpose. There you can define fine grained access control for any object base on user permissions. Heres the simple base on which acl is base uppon, too. you can throw in your own implementation of PermissionEvaluator and then make use of "hasPermission" inside the @PreAuthorize:

Link it in in your security config:

<global-method-security secured-annotations="disabled" pre-post-annotations="enabled">
        <expression-handler ref="expressionHandler"/>
    </global-method-security>

    <beans:bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
        <beans:property name="permissionEvaluator" ref="myPermissionEvaluator"/>
    </beans:bean>

create a "hasPermission" PreAuthorize constraint:

@PreAuthorize("hasPermission(#value, 'admin')")
@RequestMapping(value="/secure/{value}/data")
@ResponseBody
public String aloa(@PathVariable("value") String value, Principal principal) 

Fill a PermissionEvaluator with life. Here you can bridge your domain-permission over to spring-security: The referenced value from your @RequestMapping will come in through the "targetDomainObject" in "permission" you'll find the required permission as defined in your "hasPermission" definition above.

@Component("myPermissionEvaluator")
public class MyPermissionEvaluator implements PermissionEvaluator {

    @Override
    public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
                return ...;
    }

    @Override
    public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType,
            Object permission) {
        return ...;
    }

}

you may even directly access the Principal object from within the annotations, too:

@PreAuthorize("#value == authentication.principal.title") //my pricipal is from ldap source and title is mapped in from there.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM