简体   繁体   English

PreAuthorize不起作用

[英]PreAuthorize doesn't work

I'm writing a socket server (no web-application !) application and want to use method-based security to handle my ACL needs. 我正在编写套接字服务器(没有web应用程序!)应用程序,并希望使用基于方法的安全性来处理我的ACL需求。 i followed a small tutorial i found spring security by example 我按照一个小教程, 通过示例找到了弹簧安全性

so far i configured: 到目前为止我配置:

<security:global-method-security pre-post-annotations="enabled">
    <security:expression-handler ref="expressionHandler" />
</security:global-method-security>
<bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
    <property name="permissionEvaluator">
        <bean id="permissionEvaluator" class="myPermissionEvaluator" />
    </property>
</bean>

<security:authentication-manager id="authenticationmanager">
    <security:authentication-provider ref="authenticationprovider" />
</security:authentication-manager>
<bean id="authenticationprovider" class="myAuthenticationProvider" />

With a service bean: 使用服务bean:

@Named
public class ChannelService {
    @PreAuthorize("isAuthenticated() and hasPermission(#channel, 'CHANNEL_WRITE')")
    public void writeMessage(Channel channel, String message) { ... }
}

Everything compiles and the application starts and works fine, but without access control. 一切都编译,应用程序启动并正常工作,但没有访问控制。 My debug log shows that my Evaluator is never called. 我的调试日志显示我的Evaluator永远不会被调用。

When i tried something similar with a @Secured annotation the annotation was evaluated and access was denied. 当我尝试使用@Secured注释类似的东西时,注释被评估并且访问被拒绝。 but simple role based security isn't enough for my requirements. 但基于角色的简单安全性不足以满足我的要求。

EDIT did some more tests: when i configure only secured-annotations="enabled" the role based security works. EDIT做了一些测试:当我只配置secure-annotations =“enabled”时,基于角色的安全性工作。 when configure pre-post-annotations="enabled" in ADDITION neither secured nor preauthorize works. 当在ADDITION中配置pre-post-annotations =“enabled”时既不安全也不预授权。 when i configure only pre-post-annotations it still doesn't work. 当我只配置预注释后,它仍然无法正常工作。

EDIT2 EDIT2

some more tests: with only secured_annotations="enabled" the call to my channelservice goes through the Cglib2AopProxy as soon as i activate pre-post-annotations the call lands directly in the channelservice. 一些更多的测试:只有secured_annotations =“enabled”,我的频道服务的调用一旦激活前后注释,就会通过Cglib2AopProxy直接调用到频道服务中。 no interceptor, no proxy, nothing. 没有拦截器,没有代理,没有。

I'm getting kind of desperate... 我变得有点绝望......

EDIT3 EDIT3

I debug-logged my testruns here is the part for spring-security 我在这里调试记录我的测试是spring-security的一部分

with only secured-annotations="enabled" 只有secure-annotations =“enabled”

2012-04-12 13:36:46,171 INFO  [main] o.s.s.c.SpringSecurityCoreVersion - You are running with Spring Security Core 3.1.0.RELEASE
2012-04-12 13:36:46,174 INFO  [main] o.s.s.c.SecurityNamespaceHandler - Spring Security 'config' module version is 3.1.0.RELEASE
2012-04-12 13:36:49,042 DEBUG [main] o.s.s.a.m.DelegatingMethodSecurityMetadataSource - Caching method [CacheKey[mystuff.UserService; public void mystuff.UserService.serverBan(java.lang.String,mystuff.models.User,org.joda.time.DateTime)]] with attributes [user]
2012-04-12 13:36:49,138 DEBUG [main] o.s.s.a.i.a.MethodSecurityInterceptor - Validated configuration attributes
2012-04-12 13:36:49,221 DEBUG [main] o.s.s.a.m.DelegatingMethodSecurityMetadataSource - Caching method [CacheKey[mystuff.ChannelService; public void mystuff.ChannelService.writeMessage(mystuff.models.Channel,java.lang.String)]] with attributes [blubb]
2012-04-12 13:36:51,159 DEBUG [main] o.s.s.a.ProviderManager - Authentication attempt using mystuff.GlobalchatAuthenticationProvider
2012-04-12 13:36:56,166 DEBUG [Timer-1] o.s.s.a.ProviderManager - Authentication attempt using mystuff.GlobalchatAuthenticationProvider
2012-04-12 13:36:56,183 DEBUG [Timer-1] o.s.s.a.i.a.MethodSecurityInterceptor - Secure object: ReflectiveMethodInvocation: public void mystuff.ChannelService.writeMessage(mystuff.models.Channel,java.lang.String); target is of class [mystuff.ChannelService]; Attributes: [blubb]
2012-04-12 13:36:56,184 DEBUG [Timer-1] o.s.s.a.i.a.MethodSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@312e8aef: Principal: mystuff.UserId@ced1752b; Credentials: [PROTECTED]; Authenticated: true; Details: null; Not granted any authorities
Exception in thread "Timer-1" org.springframework.security.access.AccessDeniedException: Access is denied
    at org.springframework.security.access.vote.AbstractAccessDecisionManager.checkAllowIfAllAbstainDecisions(AbstractAccessDecisionManager.java:70)
    at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:88)
    at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:205)
    at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:59)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622)
    at mystuff.ChannelService$$EnhancerByCGLIB$$3ad5e57f.writeMessage(<generated>)
    at mystuff.run(DataGenerator.java:109)
    at java.util.TimerThread.mainLoop(Timer.java:512)
    at java.util.TimerThread.run(Timer.java:462)
2012-04-12 13:36:56,185 DEBUG [Timer-1] o.s.s.access.vote.AffirmativeBased - Voter: org.springframework.security.access.vote.RoleVoter@1cfe174, returned: 0
2012-04-12 13:36:56,185 DEBUG [Timer-1] o.s.s.access.vote.AffirmativeBased - Voter: org.springframework.security.access.vote.AuthenticatedVoter@da89a7, returned: 0

with pre-post-annotations="enabled" 带有预注释=“启用”

2012-04-12 13:39:54,926 INFO  [main] o.s.s.c.SpringSecurityCoreVersion - You are running with Spring Security Core 3.1.0.RELEASE
2012-04-12 13:39:54,929 INFO  [main] o.s.s.c.SecurityNamespaceHandler - Spring Security 'config' module version is 3.1.0.RELEASE
2012-04-12 13:39:54,989 INFO  [main] o.s.s.c.m.GlobalMethodSecurityBeanDefinitionParser - Using bean 'expressionHandler' as method ExpressionHandler implementation
2012-04-12 13:39:59,812 DEBUG [main] o.s.s.a.ProviderManager - Authentication attempt mystuff.GlobalchatAuthenticationProvider
2012-04-12 13:39:59,850 DEBUG [main] o.s.s.a.i.a.MethodSecurityInterceptor - Validated configuration attributes

As far as i understand this log output spring doesn't realize my beans need to be proxied, so they aren't and so i don't get security. 据我所知,这个日志输出spring没有意识到我的bean需要被代理,所以它们不是,所以我没有得到安全性。

EDIT4 EDIT4

I debug-logged the complete sprint startup... (thats one big log) and there i find: 我调试了完整的sprint启动...(那是一个大日志),我发现:

2012-04-12 14:40:41,385 INFO [main] o.s.c.s.ClassPathXmlApplicationContext - Bean 'channelService' of type [class mystuff.ChannelService] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)

is there a way to figure out why? 有没有办法找出原因? because as far as i understand it. 因为据我所知。 because of @preauthorize the bean should be eligible. 因为@preauthorize bean应该符合条件。 with only secured-annotations="enabled" i get a post processing log. 只有secure-annotations =“enabled”我得到一个后期处理日志。

This configuration worked just as expected for me: 这个配置对我来说就像预期的那样:

<bean id="securityExpressionHandler"
    class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler" /> 

<bean id="preInvocationAdvice"
    class="org.springframework.security.access.expression.method.ExpressionBasedPreInvocationAdvice"
    p:expressionHandler-ref="securityExpressionHandler" />

<util:list id="decisionVoters">
    <bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
    <bean class="org.springframework.security.access.vote.RoleVoter" />
    <bean class="org.springframework.security.access.prepost.PreInvocationAuthorizationAdviceVoter"
        c:pre-ref="preInvocationAdvice" />
</util:list>

<bean id="accessDecisionManager"
    class="org.springframework.security.access.vote.UnanimousBased"
    c:decisionVoters-ref="decisionVoters" />

<sec:global-method-security
    authentication-manager-ref="authenticationManager"
    access-decision-manager-ref="accessDecisionManager"
    pre-post-annotations="enabled" />

I got the log message: 我收到了日志消息:

WARN  org.springframework.security.access.expression.DenyAllPermissionEvaluator - 
    Denying user jack permission 'CHANNEL_WRITE' on object Channel[ name=null ]

And an exception: 还有一个例外:

org.springframework.security.access.AccessDeniedException: Access is denied

From a simple test: 从一个简单的测试:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:META-INF/spring/application-context.xml")
public class SpringSecurityPrePostTest {

    @Autowired
    ChannelService channelService;

    @Test
    public void shouldSecureService() throws Exception {
        Authentication authentication = new UsernamePasswordAuthenticationToken("jack", "sparrow");
        SecurityContext securityContext = SecurityContextHolder.getContext();
        securityContext.setAuthentication(authentication);

        channelService.writeMessage(new Channel(), "test");
    }
}

One thing I did diffrent was to use interface on a service and JDK proxies instead of cglib: 我做的一件事就是在服务和JDK代理上使用接口而不是cglib:

public interface ChannelService {

    void writeMessage(Channel channel, String message);
}

and: 和:

@Component
public class ChannelServiceImpl implements ChannelService {

    private static final Logger LOG = LoggerFactory.getLogger(ChannelServiceImpl.class);

    @Override
    @PreAuthorize("isAuthenticated() and hasPermission(#channel, 'CHANNEL_WRITE')")
    public void writeMessage(Channel channel, String message) {
        LOG.info("Writing message {} to: {}" , message, channel);
    }

}

UPDATE1: UPDATE1:


With this simplified config I get the same result: 使用这个简化的配置,我得到相同的结果:

<bean id="securityExpressionHandler"
    class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler" /> 

<sec:global-method-security
    authentication-manager-ref="authenticationManager"
    pre-post-annotations="enabled">
    <sec:expression-handler ref="securityExpressionHandler" />
</sec:global-method-security>

UPDATE2: UPDATE2:


The debug message from Edit4 indicates that channelService may not have bean proxied at all as it got classified as not eligible for auto-proxying . 来自Edit4的调试消息表明channelService可能根本没有代理bean,因为它被分类为not eligible for auto-proxying This qiestion answers similar problem - try not to use @Autowired or any other mechanism based on BeanPostProcessors to set up the beans involved in security checks (ie myPermissionEvaluator ). 这个qiestion解决了类似的问题 - 尽量不要使用@Autowired或基于BeanPostProcessors任何其他机制来设置安全检查中涉及的bean(即myPermissionEvaluator )。


UPDATE3: UPDATE3:


You cannot use secured resources (ie services) within beans responsible for security checks! 不能在负责安全检查的bean中使用安全资源(即服务)! This creates a dependency loop and is a error in Your configuration. 这会创建一个依赖项循环,并且是您的配置中的错误。 You must use lover level access (ie DAO) to check permissions, anything that is not secured ! 必须使用情人级别访问(即DAO)来检查权限,任何不安全的东西! Implementing security checks using secured resources is not what You want to do . 使用安全资源实施安全检查不是您想要做的

If despite using not secured resources with @Autowired things don't work as expected, try using old-school XML confiuration style for all beans involved in security checks. 如果尽管使用@Autowired没有安全资源的东西不能按预期工作,请尝试使用旧式XML配置样式来处理安全检查中涉及的所有bean。 Also remember that <context:component-scan /> is in fact a BeanDefinitionRegistryPostProcessor and introduces the scanned beans into the BeanFactory after all the ones declared in XML are already there. 还要记住<context:component-scan />实际上是一个BeanDefinitionRegistryPostProcessor并且在XML中声明的所有bean已经存在之后,将扫描的bean引入BeanFactory

it works, make sure that you have <sec:global-method-security pre-post-annotations="enabled"/> in your spring servlet (ie where you may have your <mvc:annotation-driven/> ) 它有效,确保你的spring servlet中有<sec:global-method-security pre-post-annotations="enabled"/> (即你的<mvc:annotation-driven/>

"sec" is from xmlns:sec="http://www.springframework.org/schema/security" “sec”来自xmlns:sec="http://www.springframework.org/schema/security"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Spring Security @PreAuthorize注释不起作用 - Spring Security @PreAuthorize annotaion doesn't work @PreAuthorize isAnonymous 在 Spring Boot 上不起作用 - @PreAuthorize isAnonymous doesn't work on Spring Boot Spring @Secured 和 @PreAuthorize 不能正常工作(总是状态 403) - Spring @Secured and @PreAuthorize doesn`t work properly(always status 403) Spring Security中的@PreAuthorize注释不起作用。 可能是错误配置的.xml文件 - @PreAuthorize annotation in Spring Security doesn't work. Might be misconfigured .xml file Mockito不使用@PreAuthorize和Spring Boot嘲笑 - Mockito doesn't mocking with @PreAuthorize and Spring Boot @PreAuthorize在Spring上不起作用 - @PreAuthorize does not work on Spring 为什么@Resource无法与@PreAuthorize一起使用 - Why does @Resource not work with @PreAuthorize 安全注释@PreAuthorize在@Controller中不生效,仅在具有Spring Security 3.2.5的@Service中生效 - Security annotation @PreAuthorize doesn't take effect in @Controller, only in @Service with Spring Security 3.2.5 使用@PreAuthorize时,Spring SpelExpression似乎无法读取我的bean - Spring SpelExpression doesn't seem to read my bean when using @PreAuthorize @Secured和@PreAuthorize注释使用哪些方法? - With which methods does @Secured and @PreAuthorize annotation work?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM