2012-04-11 7 views
5

Ich schreibe eine Socket-Server-Anwendung (keine Web-Anwendung!) Und möchte Methoden-basierte Sicherheit verwenden, um meine ACL-Anforderungen zu behandeln. Ich folgte ein kleines Tutorial i spring security by examplePreAuthorize funktioniert nicht

bisher gefunden i konfiguriert:

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

Mit einem Service-Bean:

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

Alles kompiliert und die Anwendung gestartet und funktioniert gut, aber ohne Zugriffskontrolle . Mein Debugprotokoll zeigt, dass mein Evaluator nie aufgerufen wird.

Wenn ich etwas Ähnliches mit einer @Secured Annotation versuchte, wurde die Annotation ausgewertet und der Zugriff verweigert. aber einfache rollenbasierte Sicherheit ist nicht genug für meine Anforderungen.

BEARBEITEN habe noch einige Tests durchgeführt: Wenn ich nur secured-annotations = "enabled" konfiguriere, funktioniert die rollenbasierte Sicherheit. Wenn pre-post-annotations = "enabled" in ADDITION konfiguriert wird, funktioniert weder die Sicherung noch die Vorautorisierung. Wenn ich nur Pre-Post-Annotationen konfiguriere, funktioniert es immer noch nicht.

EDIT2

einige weitere Tests: mit nur secured_annotations = „freigegeben“ der Aufruf an meine Channel geht durch die Cglib2AopProxy sobald ich den Anruf landet direkt in der Channel Prä-Post-Annotationen aktivieren . kein Abfangjäger, kein Proxy, nichts.

Ich erhalte Art verzweifelter ...

EDIT3

Debug-logged meine Testfahrt hier ist der Teil für feder Sicherheit

mit nur gesicherten Anmerkungen =“ 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.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 

mit Prä-Post-Anmerkungen = "freigegeben"

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 

Soweit ich verstehe, merkt diese Protokollausgabefeder nicht, dass meine Bohnen proxied sein müssen, also sind sie nicht und so bekomme ich Sicherheit nicht.

Edit4

ich die komplette Sprint Start Debug-logged ... (das ist ein großer Log) und dort finden i:

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) 

ist es eine Möglichkeit, um herauszufinden, warum? weil, soweit ich es verstehe. wegen @preauthorize sollte die Bean berechtigt sein. mit nur secured-annotations = "enabled" erhalte ich ein Nachbearbeitungsprotokoll.

+0

Welche Version von Spring und Spring Security verwenden Sie? – Roadrunner

+0

@Roadrunner Feder 3.1.0.RELEASE auf alles. – Laures

+1

Können Sie debuggen, wenn "PrePostAnnotationSecurityMetadataSource # getAttributes()" für Ihre Methode aufgerufen wird, wenn Spring initialisiert? – Luciano

Antwort

5

Diese Konfiguration funktioniert genauso wie für mich erwartet:

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

ich habe die Log-Nachricht:

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

Und eine Ausnahme:

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

Aus einem einfachen 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"); 
    } 
} 

Eines, was ich diffrent tat, war Schnittstelle auf einen Dienst und JDK Proxies statt cglib zu verwenden:

public interface ChannelService { 

    void writeMessage(Channel channel, String message); 
} 

und:

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


Mit diesem vereinfachten Konfigurations ich das gleiche Ergebnis:

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


Die Debug-Nachricht von Edit4 zeigt an, dass channelService nicht bean gar proxied haben, da es als not eligible for auto-proxying eingestuft wurde. This qiestion Antworten ähnliches Problem - versuchen Sie nicht @Autowired oder einen anderen Mechanismus auf BeanPostProcessors Basis zu verwenden, um die Bohnen in Sicherheitskontrollen beteiligt einzurichten (das heißt myPermissionEvaluator).


UPDATE3:


Sie kann nicht Verwendung gesichert Ressourcen (das heißt Dienste) innerhalb Bohnen verantwortlich für Sicherheitskontrollen! Dies erzeugt eine Abhängigkeitsschleife und ist ein Fehler in Ihrer Konfiguration. Sie Muss Verwendung Liebhaber Level-Zugriff (d DAO) Berechtigungen zu überprüfen, alles, was ist nicht gesichert! Die Implementierung von Sicherheitsprüfungen mit gesicherten Ressourcen ist nicht das, was Sie tun möchten.

Wenn trotz der Verwendung nicht gesicherter Ressourcen mit @Autowired die Dinge nicht wie erwartet funktionieren, versuchen Sie Old-School-XML-Konfiurationsstil für alle Beans, die an Sicherheitsprüfungen beteiligt sind.Denken Sie auch daran, dass <context:component-scan /> tatsächlich eine BeanDefinitionRegistryPostProcessor ist und führt die gescannten Beans in die BeanFactory ein, nachdem alle in XML deklarierten bereits vorhanden sind.

+0

in meinem PermissionEvaluator ist der Kanal und Benutzerdienst zu verwenden, da Benutzer permi Einstellungen zu diesen Objekten werden in diesen Objekten gespeichert. Aber '@ inject' dieser Beans bewirkt, dass diese beiden Dienste vor der PrePostAnnotationSecurityMetadataSource erstellt werden. Wenn ich sie entferne, wird mein Evaluator richtig aufgerufen. jetzt muss ich nur herausfinden, wie ich meine Proxy-Dienste in den Evaluator einsperren kann, ohne dies zu verursachen. – Laures

+0

@Laures siehe meine erweiterte Antwort für weitere Tipps. – Roadrunner

+0

Die Methoden, die ich verwende, um Berechtigungen zu überprüfen, sind nicht gesichert (und werden nicht sein), aber sie sind Teil des Dienstes, der Methoden gesichert hat. Ich löste das Problem, indem ich das Service-Objekt aus dem Anwendungskontext nachschlagen, wenn ich es brauche. vielleicht nicht die sauberste Lösung, aber in meinem Fall gibt es keine niedrigere Zugriffsebene. – Laures

-1

es funktioniert, sicher, dass Sie <sec:global-method-security pre-post-annotations="enabled"/> im Frühjahr Servlet (dh, wo Sie Ihre <mvc:annotation-driven/> haben kann)

„sec“ ist von xmlns:sec="http://www.springframework.org/schema/security"

+0

Wie Sie sehen können, habe ich bereits das global-method-security-Tag konfiguriert und das ist keine Webanwendung, also kein Servlet oder irgendetwas. – Laures

+0

@ Laures was ist der Name Annotation, die Sie verwenden? Es ist nicht eine Feder Annotation, vielleicht sollten Sie versuchen, mit Component anntotation –

+0

named ist eine jsr330 Annotation, die im Grunde bedeutet das gleiche wie Komponente, aber seine standardisierte und nicht Frühjahr spezifische. Jsr 330 ist bis zum Frühjahr implementiert – Laures

Verwandte Themen