@PreAuthorize 注释不起作用弹簧安全性
Posted
技术标签:
【中文标题】@PreAuthorize 注释不起作用弹簧安全性【英文标题】:@PreAuthorize annotation not working spring security 【发布时间】:2012-08-04 04:25:03 【问题描述】:我发现了很多类似的问题,但没有一个能解决我的问题。
我的问题是ROLE_USER
可以访问ROLE_ADMIN
的功能
我的 spring-security.xml 代码如下。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:s="http://www.springframework.org/schema/security"
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.0.xsd">
<s:http auto-config="true" use-expressions="true">
<s:intercept-url pattern="/index.jsp" access="permitAll" />
<s:intercept-url pattern="/welcome*" access="hasRole('ROLE_USER')" />
<s:intercept-url pattern="/helloadmin*" access="hasRole('ROLE_ADMIN')" />
<s:form-login login-page="/login" default-target-url="/welcome"
authentication-failure-url="/loginfailed" />
<s:logout logout-success-url="/logout" />
</s:http>
<s:authentication-manager>
<s:authentication-provider>
<s:user-service>
<s:user name="asif" password="123456" authorities="ROLE_USER,ROLE_ADMIN" />
<s:user name="raheel" password="123456" authorities="ROLE_USER" />
</s:user-service>
</s:authentication-provider>
</s:authentication-manager>
当我添加<s:global-method-security pre-post-annotations="enabled"/>
我的代码显示资源未找到错误,当我删除我的代码时执行成功,但 ROLE_USER
可以访问 ROLE_ADMIN
函数
我的控制器功能是。
@PreAuthorize("hasRole('ROLE_ADMIN')")
@RequestMapping(value="/delete", method = RequestMethod.GET)
public String DeleteAll(ModelMap model, Principal principal )
org.springframework.security.core.userdetails.User activeUser = (org.springframework.security.core.userdetails.User)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
System.out.println("Active user is "+activeUser.getUsername()+"Authorities are "+activeUser.getAuthorities());
return "deleteUsers";
【问题讨论】:
【参考方案1】:我在使用注释时遇到了同样的问题,问题是我的控制器中没有 @Controller 注释。
看来你需要:
Spring Security 配置中的这些注释:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
控制器中的这些注释:
@Controller
public class ServiceRS
@RequestMapping(value = "/admin", method = RequestMethod.GET)
@PreAuthorize("hasAuthority('ROLE_ADMIN')")
public void wsAdmin()
[...]
另外,如果您仍有问题,请考虑将其添加到您的 log4j2 配置中:
<Logger name="org.springframework.security" level="trace" additivity="false">
<AppenderRef ref="Console" />
<AppenderRef ref="RollingRandomAccessFile" />
</Logger>
如果 Spring 考虑您的注释,您将在日志中看到:
TRACE org.springframework.security.access.prepost.PrePostAnnotationSecurityMetadataSource [main] Looking for Pre/Post annotations for method 'wsAdmin' on target class '***.ServiceRS'
DEBUG org.springframework.security.access.prepost.PrePostAnnotationSecurityMetadataSource [main] @org.springframework.security.access.prepost.PreAuthorize(value=hasAuthority('ROLE_ADMIN')) found on specific method: public void ***.ServiceRS.wsAdmin()
DEBUG org.springframework.security.access.method.DelegatingMethodSecurityMetadataSource [main] Caching method [CacheKey[***.ServiceRS; public void ***.ServiceRS.wsAdmin()]] with attributes [[authorize: 'hasAuthority('ROLE_ADMIN')', filter: 'null', filterTarget: 'null']]
显然你可以考虑在org.springframework.security.access.expression.SecurityExpressionRoot中的相应方法中添加断点,以查看是否使用注释中的条件完成了调用。
问候。
【讨论】:
【参考方案2】:将下面的标签放在另一个spring配置文件中,而不是spring安全配置文件中。
我也遇到了同样的错误。
<security:global-method-security secured-annotations="enabled" proxy-target-class="true"/>
【讨论】:
【参考方案3】:如果您使用的是 XML 配置,请不要忘记添加以下属性:
<s:global-method-security pre-post-annotations="enabled"/>
如果您使用的是 Java Configuration,请不要忘记添加以下注解:
@EnableGlobalMethodSecurity(prePostEnabled = true)
【讨论】:
【参考方案4】:你应该有
<s:global-method-security pre-post-annotations="enabled"/>
如果您希望 @PreAuthorize
注释起作用。
回答评论:
您似乎缺少 spring-aop
依赖项。
如果你使用的是 maven,你需要:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>$org.springframework.version</version>
</dependency>
如果没有,您可以从here 获取罐子。
【讨论】:
是的,我知道,但是当我添加我也面临同样的问题。当我将以下元素从 applicationContext.xml 移动到 *-servlet.xml(我的调度程序的配置 xml)时,我的问题解决了。
<security:global-method-security secured-annotations="enabled"/>
您必须在调度程序的 xml 中包含此元素,而不是在应用程序的 xml 中。Spring FAQ
【讨论】:
如果您至少没有在 servlet 的 xml 配置中定义 global-security-method,这绝对是正确的答案- 这是确切的问题,+1 用于提及 Spring FAQ 链接以进行解释。【参考方案6】:在使用带有 Web 异步支持的 Servlet 3 时会出现此问题。 Spring Security 3.1.4 及以下版本一旦进入Callable
方法的匿名方法,就会失去它们的安全上下文。
升级Spring Security to 3.2.0 RC1 将解决您的问题。
Maven 依赖:
<dependencies>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>3.2.0.RC1</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>3.2.0.RC1</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>http://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>http://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
【讨论】:
【参考方案7】:以上答案都不适合我。我不得不走添加安全装饰器的路线。
装饰器被放置在文件servlet-context.xml
中的bean上。
首先将安全模式添加到 XML 命名空间:
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
...
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
然后将装饰器应用到服务 bean 的实现上,像这样..
<beans:bean id="myService" class="my.service.impl.MyServiceImpl" scope="request">
<security:intercept-methods>
<security:protect access="ROLE_USER" method="get*"/>
<security:protect access="ROLE_ADMIN" method="set*"/>
</security:intercept-methods>
</beans:bean>
【讨论】:
【参考方案8】:这可能对你有帮助:
<security:global-method-security secured-annotations="enabled" proxy-target-class="true"/>
问候。
【讨论】:
【参考方案9】:试试@Secured注解,
那么你就有了
@Secured("ROLE_ADMIN")
@RequestMapping(value="/delete", method = RequestMethod.GET)
public String DeleteAll(ModelMap model, Principal principal )
...
这里是a detailed blog post about it。
【讨论】:
以上是关于@PreAuthorize 注释不起作用弹簧安全性的主要内容,如果未能解决你的问题,请参考以下文章
使用 mongodb PostAuthorize 和 PreAuthorize 的 Spring Boot 安全性不起作用