2012-09-26 9 views
5

@RequestBodyをスプリングセキュリティで保護する適切な方法は何ですか?例えばスプリング保証@RequestBody

Userは複数Blog Sを有することができ、各Blogは複数Entry Sを有することができます。ユーザーが特定のブログにエントリを保存するために行くと、要求は次のようにでてくるでしょう:

@RequestMapping(value="/api/entry", method=RequestMethod.POST) 
@ResponseBody 
public Entry save(@Valid @RequestBody Entry entry) { 
    this.entryService.save(entry); 
    return entry; 
} 

今、入ってくるentryBlogを持って、ユーザーは、要求を細工し、他の誰かのブログを選択している可能性が効果的にエントリーを自分のブログに投稿します。検証でこれをキャッチすることはできますが(BlogがログインしたUserに属していることを確認するためにパーシスタンス層を照会する)、私はこれをSpring Securityが処理する必要があると感じています。もしそうなら、私はこれをどうやってやるの?

答えて

6

このような状況がありました。

ここに2つの解決策があります。私は春が決定クラスから静的ISOK()メソッドを呼び出しますその場合、//

または

@RequestMapping(value="/api/entry", method=RequestMethod.POST) 
    @ResponseBody 
    @PreAuthorize("Decision.isOK(entry, principal)") 
    public Entry save(@Valid @RequestBody Entry entry, Principal principal) { 
     this.entryService.save(entry); 
     return entry; 
    } 

@RequestMapping(value="/api/entry", method=RequestMethod.POST) 
@ResponseBody 
@PreAuthorize("#entry.author.name == principal.name)" 
public Entry save(@Valid @RequestBody Entry entry, Principal principal) { 
    this.entryService.save(entry); 
    return entry; 
} 

あまり好きではありませんでした。ブール値を返す必要があります。

Springは、プリンシパルプリンシパルプリンシパルの認証されたオブジェクトをメソッドに挿入しますが、心配する必要はありません。 アスペクトを使用して

<security:global-method-security pre-post-annotations="enabled" />

セカンドで@PreAuthorize注釈を有効にします。アスペクトを作成する。

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.METHOD) 
public @interface Protector { 
} 

@Aspect 
@Component 
public class MyAspect { 
    @Before("@annotation(com.xyz.Protector)") 
    public void before(JoinPoint joinPoint) throws Throwable { 
     //u can get method object from joinPoint object, 
     Method method = ((MethodSignature)joinPoint.getMethodSignature()).getMethod(); 
     //As long as you have Method object you can read the parameter objects (Entry and Principal) with reflection. 
     //So Compare here: If entry.getOwner().getId().equal(principal.getName()) blah blah blah 
    } 
} 

@RequestMapping(value="/api/entry", method=RequestMethod.POST) 
@ResponseBody 
@Protector 
public Entry save(@Valid @RequestBody Entry entry, Principal principal) { 
    this.entryService.save(entry); 
    return entry; 
} 

あなたは側面を持っている場合は、ランタイム

上でより多くの所有を持つことができます。また、私は `PreAuthorize` @で最も幸せだった両方のアプローチを試みた後、このulr

+1

を参照してください。誰かがこれを見て、reqのボディを確保することは私のためにやや複雑で、私はいくつかのサービスでBeanを結びつけることができました。 Beanインスタンスを呼び出すとELが少し変化します。例: '@PreAuthorize(" @ entry.blog.id、principal) ")' –

+1

'@ PreAuthorize'はまさにこの目的のためのものですが、@Aspectはより一般的です。 ) – Elbek

+0

@PreAuthorizeのSpring-ELからの参照メソッドのパラメータには、シャープな '' '' '' '' ''という接頭辞を付ける必要があります。 @PreAuthorize( "Decision.isOK(entry、principal)") '' ''の代わりに '' Decision.isOK(#entry、#principal)」) '' ''の代わりに '' Decision.isOK –

関連する問題