java @PreAuthorize 不适用于方法安全规则和方法参数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15360965/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
@PreAuthorize does not work with method security rules and method parameters
提问by Spacemonkey
I am adding Spring Security to one Spring project. The architecture of the system is REST and user can access to different resources.
我正在将 Spring Security 添加到一个 Spring 项目中。系统架构为REST,用户可以访问不同的资源。
I would like to give access to personal information to administrators and users that are owners of this information. I have started simple: filtering user profile like this:
我想向作为此信息所有者的管理员和用户授予访问个人信息的权限。我开始很简单:像这样过滤用户配置文件:
In my service layerI wanted to use method annotations and include method parameters..
在我的服务层中,我想使用方法注释并包含方法参数..
@PreAuthorize("hasRole('ROLE_ADMIN') or principal.userId == #id")
public Usuario getUser(int id) throws DAOException {
...
}
But this is not working at all. Any user can see all profiles (admins and all users also) when this URL is requested (Web layer):
但这根本行不通。请求此 URL 时,任何用户都可以看到所有配置文件(管理员和所有用户)(Web 层):
@RequestMapping(value="/user/{uid}", method=RequestMethod.GET)
public ModelAndView getUser(@PathVariable int uid) throws DAOException {
userDAO = new UsuarioJPADAO();
userService.setUsuarioDAO(userDAO);
return new ModelAndView("user", "user", userService.getUser(uid));
}
Here is my security.xml
这是我的 security.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.1.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<!-- Security Annotations -->
<global-method-security
pre-post-annotations="enabled"/>
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/css/**" access="permitAll" />
<intercept-url pattern="/images/**" access="permitAll" />
<intercept-url pattern="/js/**" access="permitAll" />
<intercept-url pattern="/favicon.ico" access="permitAll" />
<intercept-url pattern="/login" access="permitAll" />
<intercept-url pattern="/users" access="hasRole('ROLE_ADMIN')" />
<intercept-url pattern="/users/page/*" access="hasRole('ROLE_ADMIN')" />
<intercept-url pattern="/customers" access="hasRole('ROLE_ADMIN')" />
<intercept-url pattern="/employees" access="hasRole('ROLE_ADMIN')" />
<intercept-url pattern="/search/*" access="hasRole('ROLE_ADMIN')" />
<intercept-url pattern="/*" access="hasAnyRole('ROLE_ADMIN, ROLE_EMPLOYEE, ROLE_PARTNER, ROLE_USER')" />
<intercept-url pattern="/*/*" access="hasAnyRole('ROLE_USER, ROLE_ADMIN')" />
<intercept-url pattern="/*/*/*" access="hasAnyRole('ROLE_USER, ROLE_ADMIN')" />
<intercept-url pattern="/*/*/*/*" access="hasAnyRole('ROLE_USER, ROLE_ADMIN')" />
<intercept-url pattern="/*/*/*/*/*" access="hasAnyRole('ROLE_USER, ROLE_ADMIN')" />
<intercept-url pattern="/*/*/*/*/*/*" access="hasAnyRole('ROLE_USER, ROLE_ADMIN')" />
<intercept-url pattern="/*/*/*/*/*/*/*" access="hasAnyRole('ROLE_USER, ROLE_ADMIN')" />
<form-login login-page="/login" login-processing-url="/doLogin"
authentication-failure-url="/login?error"
username-parameter="username" password-parameter="password"
default-target-url="/default" />
<logout invalidate-session="true" logout-success-url="/login?logout" logout-url="/logout"/>
</http>
<authentication-manager>
<authentication-provider user-service-ref="UsuarioService">
</authentication-provider>
</authentication-manager>
I have checked Spring Security 3.1 bookand apparently my configuration is as book suggests. I have read other Stack Overflow posts (hereand here) but I had no luck.
我检查了Spring Security 3.1 的书,显然我的配置是书上建议的。我已经阅读了其他 Stack Overflow 帖子(这里和这里),但我没有运气。
Update:Added application-context.xml
更新:添加application-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:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<context:annotation-config />
<context:component-scan base-package="com.pe.fs" />
<mvc:annotation-driven />
<mvc:resources mapping="/**" location="/" />
<mvc:interceptors>
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<property name="paramName" value="lang" />
</bean>
</mvc:interceptors>
<!-- DataSource -->
<bean id="jpaDataSource" class="oracle.jdbc.pool.OracleDataSource"
destroy-method="close"
p:driverType="oracle.jdbc.OracleDriver"
p:user="**********"
p:password="**********"
p:uRL="jdbc:oracle:thin:@localhost:1521:XE"
/>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceXmlLocation" value="classpath*:META-INF/persistence.xml"></property>
<property name="persistenceUnitName" value="freesunPU" />
<property name="dataSource" ref="jpaDataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
<property name="showSql" value="false" />
</bean>
</property>
<property name="loadTimeWeaver">
<bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
p:entityManagerFactory-ref="entityManagerFactory" />
<tx:annotation-driven mode="aspectj"/>
<context:load-time-weaver aspectj-weaving="autodetect" />
Update:I have added spring-security-aspects
to POM and no changes. Other changes suggested in answers have been tested with but annotations such @PreAuthorize
are still not working. Cna this be a problem between contexts? Can be the usage of aspectJ the reason?
更新:我已经添加spring-security-aspects
到 POM 中,没有任何变化。答案中建议的其他更改已经过测试,但此类注释@PreAuthorize
仍然无效。这可能是上下文之间的问题吗?可能是aspectJ的使用原因吗?
What am I doing wrong?
我究竟做错了什么?
采纳答案by Spacemonkey
Finally I found solution. In SO I found some usefull answers. See hereand here.
最后我找到了解决方案。在 SO 中,我找到了一些有用的答案。请参阅此处和此处。
I moved global-method-security
to application-context.xml
which is the context of my services.
我感动global-method-security
于application-context.xml
这是我的服务范围内。
<security:global-method-security
mode="aspectj"
secured-annotations="enabled"
jsr250-annotations="disabled"
pre-post-annotations="enabled"/>
Where mode="aspectj"
as Javadoc says:
凡mode="aspectj"
为的Javadoc说:
...can be used to specify that AspectJ should be used instead of the default Spring AOP. If set, secured classes must be woven with the AnnotationSecurityAspect from the spring-security-aspects module.
...可用于指定应使用 AspectJ 而不是默认的 Spring AOP。如果设置,安全类必须与来自 spring-security-aspects 模块的 AnnotationSecurityAspect 编织在一起。
Of course, I have added to POM spring-security-aspects
:
当然,我已经添加到 POM spring-security-aspects
:
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-aspects</artifactId>
<version>3.1.3.RELEASE</version>
</dependency>
回答by Arjun Thakur
The alternative way to make it work is to add the following code in your security.xml
使其工作的另一种方法是在您的 security.xml 中添加以下代码
<intercept-url pattern="/user/**" access="hasRole('ROLE_ADMIN')" />
It will ensure that only admin can access the resources starting with pattern /user/.
它将确保只有管理员可以访问以模式 /user/ 开头的资源。
回答by Maksym Demidas
Add new interface:
添加新界面:
public interface UserService extends UserDetailsService {
Usuario getUser(int id) throws DAOException
}
Implement it in your user service and try again. Spring will be able add requested authorization checks using JDK proxies.
在您的用户服务中实现它并重试。Spring 将能够使用 JDK 代理添加请求的授权检查。
As another option you can configure Spring to use some more heavyweight libraries like Javassist or even AspectJ.In this case interface will be not necessary.
作为另一种选择,您可以将 Spring 配置为使用一些更重量级的库,例如 Javassist 甚至 AspectJ。在这种情况下,不需要接口。
EDIT.Make sure that global-method-security
is declared in the same spring context with your user service bean.
编辑。确保global-method-security
在与您的用户服务 bean 相同的 spring 上下文中声明。