2012-04-11 5 views
5

Я пишу приложение сокета-сервера (не веб-приложение!) И хочу использовать защиту на основе методов для обработки моих потребностей в ACL. я последовал небольшой учебник я нашел spring security by examplePreAuthorize не работает

до сих пор я сконфигурированный:

<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" /> 

С службы боба:

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

Все компилирует и запуска приложения и работает нормально, но без контроля доступа , Мой журнал отладки показывает, что мой Evaluator никогда не вызывается.

Когда я попытался что-то подобное с аннотацией @Secured, аннотация была оценена и доступ был отклонен. но для моих требований недостаточно простой защиты на основе ролей.

EDIT Проделал еще несколько тестов: когда я настраиваю только защищенные аннотации = "включено", службы безопасности на основе ролей. при настройке pre-post-annotations = "enabled" в ДОПОЛНЕНИИ не обеспечивается ни защита, ни предварительная авторизация. когда я настраиваю только предварительные аннотации, он все равно не работает.

EDIT2

еще несколько тестов: только с secured_annotations = «включен» призыв к моей ChannelService проходит через Cglib2AopProxy как только я активировать предварительно пост-аннотации земли вызовов непосредственно в ChannelService , нет перехватчика, нет прокси, ничего.

Я получаю вид отчаянные ...

EDIT3

Я отлаживать протоколирование моих testruns здесь часть весны-безопасность

с только обеспеченными-аннотациями =» включен»

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.springframew[email protected]312e8aef: Principal: [email protected]; 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: [email protected], returned: 0 
2012-04-12 13:36:56,185 DEBUG [Timer-1] o.s.s.access.vote.AffirmativeBased - Voter: [email protected]a7, returned: 0 

с предварительно пост-аннотаций = "включен"

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 

Насколько я понимаю, выходная пружина журнала не понимает, что мои бобы должны быть проксимированы, поэтому их нет, и поэтому я не получаю защиту.

EDIT4

Я отладки протоколирование полного запуска спринта ... (Вот один большой лог), и там я найти:

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) 

есть способ, чтобы выяснить, почему? потому что, насколько я понимаю. из-за @preauthorize компонент должен иметь право на участие. с только secure-annotations = "enabled" я получаю журнал обработки сообщений.

+0

Какую версию Spring и Spring Security вы используете? – Roadrunner

+0

@Roadrunner spring 3.1.0.RELEASE на все. – Laures

+1

Можете ли вы отлаживать, если «PrePostAnnotationSecurityMetadataSource # getAttributes()» вызывается для вашего метода, когда Spring инициализируется? – Luciano

ответ

5

Эта конфигурация работала так же, как ожидается, для меня:

<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" /> 

Я получил сообщение журнала:

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

И исключение:

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

От простого теста:

@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"); 
    } 
} 

Одна вещь, которую я сделал diffrent, чтобы использовать интерфейс на службу и JDK прокси вместо CGLIB:

public interface ChannelService { 

    void writeMessage(Channel channel, String message); 
} 

и:

@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:


С помощью этой упрощенной конфигурации я получаю тот же результат:

<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:


Отладочное сообщение от Edit4 указывает, что channelService может не иметь прокси-сервер вообще, поскольку он классифицирован как not eligible for auto-proxying. This qiestion отвечает на аналогичную проблему - попробуйте не использовать @Autowired или любой другой механизм, основанный на BeanPostProcessors, чтобы настроить компоненты, используемые в проверках безопасности (то есть myPermissionEvaluator).


Update3:


Вы не может использование обеспеченных ресурсов (т.е. услуг) в бобах, ответственных за проверку безопасности! Это создает цикл зависимостей и является ошибкой в ​​вашей конфигурации. Вы должны использовать доступ к уровню любовника (т. Е. DAO) для проверки разрешений, ничего, что не обеспечено! Внедрение проверок безопасности с использованием защищенных ресурсов: не то, что вы хотите сделать.

Если, несмотря на использование небезопасных ресурсов с @Autowired, все не работает должным образом, попробуйте использовать стиль конфликтования старой школы для всех компонентов, включенных в проверки безопасности.Также помните, что <context:component-scan /> фактически является BeanDefinitionRegistryPostProcessor и вводит сканированные компоненты в BeanFactory после того, как все те, что объявлены в XML, уже есть.

+0

в моем PermissionEvaluator использует услугу Channel и User, потому что пользователь permi ssions на этих объектах хранятся в этих объектах. Но «@ inject» этих beans заставляет эти две службы быть созданы до PrePostAnnotationSecurityMetadataSource. когда я удаляю их, мой оценщик называется должным образом. теперь мне просто нужно выяснить, как вводить мои проксированные услуги в оценщик, не вызывая этого. – Laures

+0

@Laures см. Мой расширенный ответ для получения дополнительных советов. – Roadrunner

+0

методы, которые я использую для проверки разрешений, не защищены (и не будут), но они являются частью службы, которая имеет защищенные методы. Я решил проблему, просмотрев объект службы из контекста приложения, когда мне это в первую очередь нужно. возможно, не самое чистое решение, но в моем случае нет более низкого уровня доступа. – Laures

-1

это работает, убедитесь, что у вас есть <sec:global-method-security pre-post-annotations="enabled"/> в вашем весеннем сервлета (т.е. там, где вы можете иметь свой <mvc:annotation-driven/>)

«сек» от xmlns:sec="http://www.springframework.org/schema/security"

+0

, как вы можете видеть, у меня уже настроен тэг безопасности глобального метода, и это не веб-приложение, поэтому никакого сервлета или чего-либо еще. – Laures

+0

@ Laure, какова аннотация, которую вы используете? Это не весенняя аннотация, может быть, вы должны попробовать с аннотацией компонентов. –

+0

named - это аннотация jsr330, которая, как утверждается, означает то же самое, что и компонент, но его стандартизованный и не зависящий от пружины jsr 330. реализовано весной. – Laures

Смежные вопросы