Spring + Spring Security + hasPermission无法正常工作 [英] Spring + Spring Security + hasPermission Not working
问题描述
我正在尝试将Spring Security 3与Struts 2和Spring DI一起使用.我在代码中放入了hasRole()注释,它可以正常工作,但是hasPermission()注释不起作用.我已经制作了表达式处理程序,自定义权限评估器等.
I am trying to use Spring Security 3 with Struts 2 and Spring DI. I put hasRole() annotation in my code and it is working fine but hasPermission() annotation is not working. I have made expression handler, custom permission evaluator etc.
这是代码
applicationContext.xml
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
Here is my 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
this is 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 包裹代码.权限;
This is my 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
This is 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
this is 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()不起作用吗?
Any expert here to tell me why this hasPermission() not working ?
推荐答案
它不起作用,因为Spring AOP只能识别bean之间的调用,而不能调用同一bean的方法.
It does not work, because Spring AOP can only incercept calls between beans, but not if you invoke a method of the same bean.
因此,您可以将isAccessible
方法移至另一个bean,或者使用use AspectJ代替Spring Proxy AOP.
So either you move the isAccessible
Method to an other bean, or use use AspectJ instead of Spring Proxy AOP.
另一个想法是直接使用权限评估,而不是使用带注释的方法. (但是我不知道该怎么做.)
An other idea would be using the permission evaluation directly, instead of having the annotated method. (But I do not know exactly how this can be done.)
这篇关于Spring + Spring Security + hasPermission无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!