Bahar güvenlik ifade dili ek açıklamalarında kullanılmak üzere özel yöntemler nasıl oluşturulur


92

Açıklamalar aracılığıyla yöntem tabanlı yetkilendirme için bahar güvenlik ifade dilinde kullanılmak üzere özel yöntemler ekleyen bir sınıf oluşturmak istiyorum.

Örneğin, şöyle bir şekilde kullanılmak üzere 'customMethodReturningBoolean' gibi özel bir yöntem oluşturmak istiyorum:

  @PreAuthorize("customMethodReturningBoolean()")
  public void myMethodToSecure() { 
    // whatever
  }

Sorum şu. Mümkünse, özel yöntemlerimi oluşturmak için hangi sınıfı alt sınıfa ayırmalıyım, onu spring xml yapılandırma dosyalarında yapılandırmaya nasıl devam edebilirim ve birisi bana bu şekilde kullanılan özel bir yöntemin bir örneğini verir?


2
Şu anda bir cevap yazmak için zamanım yok ama bu kılavuzu takip ettim ve harika çalıştı: baeldung.com/… Spring Security 5.1.1 kullanıyorum.
Paul

Yanıtlar:


35

İki sınıfı alt sınıflara ayırmanız gerekecek.

İlk olarak, yeni bir yöntem ifade işleyicisi ayarlayın

<global-method-security>
  <expression-handler ref="myMethodSecurityExpressionHandler"/>
</global-method-security>

myMethodSecurityExpressionHandlerbir alt sınıf olacak DefaultMethodSecurityExpressionHandlerhangi geçersiz kılma createEvaluationContext()bir alt sınıfı ayarlayarak, MethodSecurityExpressionRootüzerinde MethodSecurityEvaluationContext.

Örneğin:

@Override
public EvaluationContext createEvaluationContext(Authentication auth, MethodInvocation mi) {
    MethodSecurityEvaluationContext ctx = new MethodSecurityEvaluationContext(auth, mi, parameterNameDiscoverer);
    MethodSecurityExpressionRoot root = new MyMethodSecurityExpressionRoot(auth);
    root.setTrustResolver(trustResolver);
    root.setPermissionEvaluator(permissionEvaluator);
    root.setRoleHierarchy(roleHierarchy);
    ctx.setRootObject(root);

    return ctx;
}

Hmm, kulağa iyi bir fikir gibi geliyor, ancak DefaultMethodSecurityExpressionHandler'ın tüm özellikleri erişimci olmadan özeldir , bu yüzden herhangi bir çirkin düşünce olmadan sınıfı nasıl genişlettiğinizi merak ettim. Teşekkürler.
Joseph Şehvet

1
TrustResolver vb. Mi demek istiyorsun? Bunların hepsinin DefaultMethodSecurityExpressionHandler'da ayarlayıcıları var (en azından Spring Security 3.0'da) Bkz .: static.springsource.org/spring-security/site/apidocs/org/…
sourcedelica

3
@ericacm Özel paketMethodSecurityExpressionRoot olmaktan nasıl kurtulursunuz ?
C. Ross

176

Bahsedilen tekniklerin hiçbiri artık işe yaramayacak. Görünüşe göre Spring, kullanıcıların SecurityExpressionRoot'u geçersiz kılmalarını önlemek için büyük çaba sarf etti.

Güvenlik açıklamalarını kullanmak için 19/11/14 Kurulum Baharını DÜZENLE:

<beans ... xmlns:sec="http://www.springframework.org/schema/security" ... >
...
<sec:global-method-security pre-post-annotations="enabled" />

Bunun gibi bir fasulye yaratın:

@Component("mySecurityService")
public class MySecurityService {
    public boolean hasPermission(String key) {
        return true;
    }
}

Sonra jsp'nizde şuna benzer bir şey yapın:

<sec:authorize access="@mySecurityService.hasPermission('special')">
    <input type="button" value="Special Button" />
</sec:authorize>

Veya bir yönteme açıklama ekleyin:

@PreAuthorize("@mySecurityService.hasPermission('special')")
public void doSpecialStuff() { ... }

Ek olarak, Bahar İfade Dilini sizin@PreAuthorize geçerli kimlik doğrulamaya ve yöntem bağımsız değişkenlerine erişmek açıklamalarınızda .

Örneğin:

@Component("mySecurityService")
public class MySecurityService {
    public boolean hasPermission(Authentication authentication, String foo) { ... }
}

Ardından @PreAuthorize, yeni yöntem imzasıyla eşleşecek şekilde öğenizi güncelleyin :

@PreAuthorize("@mySecurityService.hasPermission(authentication, #foo)")
public void doSpecialStuff(String foo) { ... }

6
@Bosh hasPermission yönteminizde, Authentication auth = SecurityContextHolder.getContext().getAuthentication();mevcut kimlik doğrulama jetonunu almak için kullanabilirsiniz .
James Watkins

2
Cevabınız için teşekkürler James. Bahar yapılandırma dosyasında mySecurityService'i tanımlamam gerekir mi?
WowBow

2
Hizmetin içinde bulunduğu paket için bir bileşen tarama kurulumunuz varsa, mySecurityService'i herhangi bir XML dosyasında tanımlamanıza gerek yoktur. Eşleşen bir bileşen taramasına sahip değilseniz, bir xml fasulye tanımı kullanmanız gerekir. @PreAuthorize org.springframework.security'den geliyor
James Watkins

3
Ek açıklamaya çekirdeğin adını şu şekilde belirtmeniz gerekebilir: @Component ("mySecurityService") veya @Named ek açıklamasını kullanmanız gerekebilir.
James Watkins 13

1
@VJS Lütfen yaptığım düzenlemeye bakın. Bu notları kullanmak için yayı yapılandırmanız gerekecektir. Kimsenin bu önemli eksik ayrıntıdan şikayet etmemesine şaşırdım :)
James Watkins

14

Teşekkürler Ericacm , ancak birkaç nedenden dolayı çalışmıyor:

  • DefaultMethodSecurityExpressionHandler'ın özellikleri özeldir (yansıma görünürlüğü istenmeyen özelliklerdir)
  • En azından Eclipse'imde bir MethodSecurityEvaluationContext nesnesini çözemiyorum

Farklılıklar, mevcut createEvaluationContext yöntemini çağırmamız ve ardından özel kök nesnemizi eklememizdir. Sonunda bir StandardEvaluationContext döndürdüm MethodSecurityEvaluationContext derleyicide çözülemeyeceği için nesne türü (ikisi de aynı arabirimden). Bu, şu anda üretimde sahip olduğum koddur.

Make MethodSecurityExpressionHandler özel kökümüzü kullanın:

public class CustomMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler  {

    // parent constructor
    public CustomMethodSecurityExpressionHandler() {
        super();
    }

    /**
     * Custom override to use {@link CustomSecurityExpressionRoot}
     * 
     * Uses a {@link MethodSecurityEvaluationContext} as the <tt>EvaluationContext</tt> implementation and
     * configures it with a {@link MethodSecurityExpressionRoot} instance as the expression root object.
     */
    @Override
    public EvaluationContext createEvaluationContext(Authentication auth, MethodInvocation mi) {
        // due to private methods, call original method, then override it's root with ours
        StandardEvaluationContext ctx = (StandardEvaluationContext) super.createEvaluationContext(auth, mi);
        ctx.setRootObject( new CustomSecurityExpressionRoot(auth) );
        return ctx;
    }
}

Bu, SecurityExpressionRoot'u genişleterek varsayılan kökün yerini alır . Burada hasRole'u hasEntitlement olarak yeniden adlandırdım:

public class CustomSecurityExpressionRoot extends SecurityExpressionRoot  {

    // parent constructor
    public CustomSecurityExpressionRoot(Authentication a) {
        super(a);
    }

    /**
     * Pass through to hasRole preserving Entitlement method naming convention
     * @param expression
     * @return boolean
     */
    public boolean hasEntitlement(String expression) {
        return hasRole(expression);
    }

}

Son olarak securityContext.xml'yi güncelleyin (ve applcationContext.xml dosyanızdan başvurulduğundan emin olun):

<!-- setup method level security using annotations -->
<security:global-method-security
        jsr250-annotations="disabled"
        secured-annotations="disabled"
        pre-post-annotations="enabled">
    <security:expression-handler ref="expressionHandler"/>
</security:global-method-security>

<!--<bean id="expressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">-->
<bean id="expressionHandler" class="com.yourSite.security.CustomMethodSecurityExpressionHandler" />

Not: @Secured ek açıklaması, farklı bir doğrulama işleyicisinden geçtiği için bu geçersiz kılmayı kabul etmeyecektir. Bu yüzden, yukarıdaki xml'de daha sonra karışıklığı önlemek için onları devre dışı bıraktım.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.