根据用户属性保护url模式Spring安全性

时间:2015-11-26 09:50:31

标签: spring spring-security

我已根据用户角色为我的项目获取了某些网址格式,如下面的spring_security xml所示。

 <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>

因此,只有管理员用户才能访问/ admin / **等。

现在我想根据不同的属性(他们的site_id只是一个int)将用户限制为他们自己的url模式。因此,只有site_id为1的用户才能访问网址“/ 1 / **”,依此类推。

我该怎么做呢?只是朝着正确的方向寻找一个点。到目前为止我看到的一切都不允许我有一个可变的url模式。如“/ {variable} /”。

1 个答案:

答案 0 :(得分:1)

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

参见“15.3方法安全表达式”

您可以使用类似

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

只有在您提供“value = 123”作为请求参数时,才会允许您进入。

您也可以在这里使用@PathVariable:

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

如果您希望对域对象进行细粒度访问控制,则可能需要将spring-acl用于此目的。在那里,您可以根据用户权限为任何对象定义细粒度访问控制。下面是acl基础uppon的简单基础。你可以抛出你自己的PermissionEvaluator实现,然后在@PreAuthorize中使用“hasPermission”:

将其链接到您的安全配置中:

<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>

创建“hasPermission”PreAuthorize约束:

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

为PermissionEvaluator填充生命。在这里,您可以将域权限桥接到spring-security:来自@RequestMapping的引用值将通过“权限”中的“targetDomainObject”进入,您将找到上面“hasPermission”定义中定义的必需权限。

@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 ...;
    }

}

您甚至可以直接从注释中访问Principal对象:

@PreAuthorize(“#value == authentication.principal.title”)//我的主要来自ldap源,标题从那里映射。