2012-04-11 25 views
5

Piszę aplikację serwera gniazd (bez aplikacji WWW!) I chcę używać zabezpieczeń opartych na metodach do obsługi moich potrzeb ACL. Poszedłem za mały samouczek znalazłem spring security by examplePreAuthorize nie działa

tak daleko i skonfigurowane:

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

Z fasoli usług:

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

Wszystko kompiluje i uruchomieniu aplikacji i działa poprawnie, ale bez kontroli dostępu . Mój dziennik debugowania pokazuje, że mój oceniający nigdy nie jest wywoływany.

Po wypróbowaniu czegoś podobnego z adnotacją @Secured adnotacja została oceniona, a dostęp został odrzucony. ale proste bezpieczeństwo oparte na rolach nie jest wystarczające dla moich wymagań.

EDIT zrobił kilka testów: Kiedy skonfigurować tylko zabezpieczonych-adnotacje = „włączony” dzieła zabezpieczeń opartych roli. po skonfigurowaniu adnotacji przed-po = "włączono" w DODATKU nie zabezpieczono ani nie wykonałem autoryzacji prac. kiedy konfiguruję tylko adnotacje przed postem, nadal nie działa.

EDIT2

kilka testów: z zaledwie secured_annotations = „Enabled” wezwanie do mojego channelservice przechodzi Cglib2AopProxy jak najszybciej aktywować pre-post-adnotacje ziemie połączenie bezpośrednio w channelservice . bez przechwytywacza, bez pośrednika, nic.

Dostaję rodzaju zdesperowany ...

Edit3

debugować rejestrowane moje testruns Oto część do wiosny bezpieczeństwa

z tylko zabezpieczone-adnotacji =” włączony”

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 

z pre-post-adnotacji = "włączony"

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 

O ile rozumiem, to źródło danych wyjściowych dziennika nie zdaje sobie sprawy, że moje fasole muszą być proxy, więc tak nie jest i dlatego nie otrzymuję zabezpieczeń.

EDIT4

debugować rejestrowane kompletny starcie sprintu ... (to jeden wielki dziennik) i nie mogę znaleźć:

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) 

czy istnieje sposób aby dowiedzieć się, dlaczego? ponieważ o ile to rozumiem. z powodu @preauthorize, komponent bean powinien kwalifikować się. tylko z zabezpieczonymi adnotacjami = "włączone" otrzymuję dziennik przetwarzania postów.

+0

Jakiej wersji Spring and Spring Security używasz? – Roadrunner

+0

@Roadrunner spring 3.1.0.RELEASE on everything. – Laures

+1

Czy można debugować, jeśli "PrePostAnnotationSecurityMetadataSource # getAttributes()" jest wywoływana dla metody po inicjalizacji Spring? – Luciano

Odpowiedz

5

Ta konfiguracja działa tak jak oczekiwano dla mnie:

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

dostałem wiadomość dziennika:

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

I wyjątek:

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

Od prostego testu:

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

Jedno zrobiłem rozróżnianie był w użyciu interfejs na obsługę i JDK proxy zamiast cglib:

public interface ChannelService { 

    void writeMessage(Channel channel, String message); 
} 

i:

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


Z tej uproszczonej konfiguracji uzyskać ten sam wynik:

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


Komunikat debugowania z Edit4 wskazuje, że channelService może nie mieć proxy w ogóle, ponieważ został sklasyfikowany jako not eligible for auto-proxying. This qiestion odpowiedzi podobny problem - Staraj się nie używać @Autowired lub innego mechanizmu opartego na BeanPostProcessors skonfigurować fasolę zaangażowanych w kontrolę bezpieczeństwa (tj myPermissionEvaluator).


UPDATE3:


Ty może nie użytku zabezpieczone zasoby (czyli usługi) w fasoli odpowiedzialnych za kontrolę bezpieczeństwa! Tworzy to pętlę zależności i jest błędem w Twojej konfiguracji. Ci koniecznością dostępu użycie poziom kochanek (tj DAO), aby sprawdzić uprawnienia, że ​​coś jest nie zabezpieczona! Wdrażanie sprawdzeń bezpieczeństwa przy użyciu zabezpieczonych zasobów to nie to, co chcesz zrobić.

Jeśli pomimo używania niezabezpieczonych zasobów z @Autowired rzeczy nie działają zgodnie z oczekiwaniami, spróbuj użyć old-school XML confiuration style dla wszystkich ziaren zaangażowanych w kontrole bezpieczeństwa.Pamiętaj też, że <context:component-scan /> jest w rzeczywistości BeanDefinitionRegistryPostProcessor i wprowadza zeskanowane ziarna do BeanFactory po tym, jak wszystkie deklarowane w XML już istnieją.

+0

w moim PermissionEvaluator jest użycie usługi Channel and User, ponieważ użytkownik permi Psy na tych obiektach są przechowywane w tych obiektach. Ale "wstrzyknięcie" tych ziaren powoduje, że te dwie usługi są tworzone przed PrePostAnnotationSecurityMetadataSource. kiedy je usuwam, mój oceniający jest poprawnie wywoływany. teraz muszę tylko wymyślić, jak wprowadzić moje usługi proxy do ewaluatora, nie powodując tego. – Laures

+0

@Leki zobacz moją rozszerzoną odpowiedź, aby uzyskać więcej wskazówek. – Roadrunner

+0

Metody używane do sprawdzania uprawnień nie są zabezpieczone (i tak nie będzie), ale są częścią usługi, która ma zabezpieczone metody. Rozwiązałem problem, szukając obiektu usługi z kontekstu aplikacji, kiedy najpierw go potrzebuję. może nie najczystsze rozwiązanie, ale w moim przypadku nie ma niższego poziomu dostępu. – Laures

-1

działa upewnij się, że masz <sec:global-method-security pre-post-annotations="enabled"/> w wiosennej serwletu (tj gdzie możesz mieć swój <mvc:annotation-driven/>) „SEC”

wynosi od xmlns:sec="http://www.springframework.org/schema/security"

+0

jak widać mam już skonfigurowany znacznik bezpieczeństwa globalnej metody i to nie jest aplikacja internetowa, więc nie ma apletu ani nic takiego. – Laures

+0

@ Laures to, co nazywa się adnotacją, której używasz - nie jest to adnotacja wiosenna, może powinieneś wypróbować komponentową anotację, którą nazwano –

+0

to adnotacja jsr330, która zasadniczo oznacza to samo co komponent, ale jest standaryzowana, a nie sprężynowa. wdrożone wiosną – Laures

Powiązane problemy