我正在尝试使用Spring Security 3和Struts 2以及Spring DI。我在我的代码中放了hasRole()注释,它工作正常,但hasPermission()注释不起作用。我已经创建了表达式处理程序,自定义权限评估程序等。
这是代码
的applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<import resource="mySecurity.xml"/>
<bean id="myAction" name="myAction" class="code.action.MyAction" autowire="byName">
</bean>
<bean id="permission" name="permission" class="code.permission.Permission" autowire="byName">
</bean>
<bean id="myEntity" name="myEntity" class="code.entities.MyEntity" autowire="byName">
</bean>
<bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler"
name="expressionHandler" autowire="byName">
</bean>
<bean class="code.permission.MyCustomPermissionEvaluator" id="customPermissionEvaluator" name="customPermissionEvaluator" autowire="byName" />
</beans>
这是我的acl-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.0.xsd">
<!-- Declare a simple map containing all our roles -->
<util:map id="permissionsMap">
<entry key="ROLE_USER" value-ref="user"/>
</util:map>
<!-- Declare permissions for Admin
Contains a map of objects and their associated allowed actions -->
<bean id="user" class="code.permission.Permission" >
<property name="objects">
<map>
<entry key="code.entities.MyEntity">
<list>
<value>READ</value>
</list>
</entry>
</map>
</property>
</bean>
</beans>
这是mySecurity.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<!-- To enable Method Security Expressions and custom PermissionEvaluator
we need to add the following -->
<global-method-security pre-post-annotations="enabled">
<expression-handler ref="expressionHandler" />
</global-method-security>
<!-- To use hasPermission() expressions, we have to configure a PermissionEvaluator -->
<!-- See 15.3.2 Built-In Expression
@http://static.springsource.org/spring-security/site/docs/3.0.x/reference/el-access.html#el-permission-evaluator -->
<beans:bean id="expressionHandler"
class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler" name="expressionHandler" autowire="byName">
<beans:property name="permissionEvaluator" ref="customPermissionEvaluator" />
<beans:property name = "roleHierarchy" ref="roleHierarchy"/>
</beans:bean>
<!-- Declare a custom PermissionEvaluator interface -->
<beans:bean class="code.permission.MyCustomPermissionEvaluator" id="customPermissionEvaluator" name="customPermissionEvaluator" autowire="byName" />
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/index.jsp" access="permitAll" />
<intercept-url pattern="/firstPage" access="hasRole('ROLE_USER')" />
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="user" password="user" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
<!-- http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/access/hierarchicalroles/RoleHierarchyImpl.html -->
<beans:bean id="roleHierarchy" class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl" name="roleHierarchy" autowire="byName">
<beans:property name="hierarchy">
<beans:value>
ROLE_USER
</beans:value>
</beans:property>
</beans:bean>
</beans:beans>
这是我的Permission.java package code.permission;
import java.util.List;
import java.util.Map;
/**
* Contains a map of objects and their associated allowed actions
*/
public class Permission {
/**
* A Map containing a list of objects and their corresponding actions
* <p>
* String: key name of the object
* List<String>: a list of permissions
*/
private Map<String, List<String>> objects;
public Map<String, List<String>> getObjects() {
return objects;
}
public void setObjects(Map<String, List<String>> objects) {
this.objects = objects;
}
}
这是myCustomPermissionEvaluator.java
package code.permission;
import java.io.Serializable;
import java.util.Collection;
import java.util.Map;
import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import javax.annotation.Resource;
public class MyCustomPermissionEvaluator implements PermissionEvaluator {
@Resource(name="permissionsMap")
private Map permissionsMap;
@Resource(name="roleHierarchy")
private RoleHierarchy roleHierarchy;
public boolean hasPermission(Authentication authentication,
Object targetDomainObject, Object permission) {
System.out.println("First hasPermission");
String role = getRole(authentication);
return hasPermission(role, permission, targetDomainObject);
}
/**
* Another hasPermission signature. We will not implement this.
*/
public boolean hasPermission(Authentication authentication,
Serializable targetId, String targetType, Object permission) {
return false;
}
/**
* Retrieves the user's highest role
*/
private String getRole(Authentication authentication) {
String highestRole = null;
try {
Collection<GrantedAuthority> auths = (Collection<GrantedAuthority>) roleHierarchy.getReachableGrantedAuthorities(authentication.getAuthorities());
for (GrantedAuthority auth: auths) {
highestRole = auth.getAuthority();
break;
}
} catch (Exception e) {
}
return highestRole;
}
private Boolean hasPermission(String role, Object permission, Object domain) {
System.out.println("Second hasPermission");
if ( permissionsMap.containsKey(role) ) {
Permission userPermission = (Permission) permissionsMap.get(role);
if ( userPermission.getObjects().containsKey(domain.getClass().getName())){
for (String action: userPermission.getObjects().get(domain.getClass().getName()) ) {
if (action.equals(permission)) {
return true;
}
}
}
}
return false;
}
}
这是MyAction.java
package code.action;
import org.springframework.security.access.prepost.PreAuthorize;
import code.entities.MyEntity;
public class MyAction {
@PreAuthorize("hasRole('ROLE_USER')")
public String showPage(){
System.out.println("in MyAction : showPage");
MyEntity entity = new MyEntity();
if(isAccessible(entity))
return "success";
else
return "input";
}
@PreAuthorize("hasPermission(#entity,'WRITE')")
public boolean isAccessible(MyEntity entity){
System.out.println("in MyAction : isAccessible");
return true;
}
}
这里的任何专家都告诉我为什么这个hasPermission()无效?
答案 0 :(得分:7)
它不起作用,因为Spring AOP只能触发bean之间的调用,但是如果你调用同一个bean的方法则不行。
因此,要么将isAccessible
方法移动到其他bean,要么使用AspectJ而不是Spring Proxy AOP。
另一个想法是直接使用权限评估,而不是使用带注释的方法。 (但我不确切知道如何做到这一点。)