2012-09-26 14 views
5

Jaki jest właściwy sposób zabezpieczenia urządzenia @RequestBody za pomocą Spring Security?Zabezpieczenie sprężynowe @RequestBody

Na przykład: może mieć wiele Blog s, a każde Blog może mieć wiele s. Entry. Użytkownik przechodzi do zapisania wpisu do pewnego bloga i prośba by się tak:

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

Teraz przychodzące entry ma Blog użytkownik mógł leczył się na wniosek i wybrał kogoś innego bloga, skutecznie publikuje wpis na swoim blogu. Chociaż mogłem złapać to w walidacji (przeszukaj warstwę trwałości, aby sprawdzić, czy Blog należy do zalogowanego User) Uważam, że powinno to być obsługiwane przez Spring Security. Jeśli tak, jak mam to zrobić?

Odpowiedz

6

Mieliśmy tego rodzaju sytuację.

Oto dwa rozwiązania. Nie lubiłem dużo

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

lub

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

// W tym przypadku sprężyna nazywają swoją statyczną metodę Isok() z klasy decyzyjnej. Powinien zwrócić wartość boolean.

Wstrzykiwanie sprężyn Główne źródło autoryzowanego obiektu dla metody, nie musisz się tym martwić. Włącz @PreAuthorize adnotacji z

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

drugie Korzystanie aspekt. Utwórz aspekt.

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

Jeśli masz aspekt można mieć więcej posiadaniem na starcie

odnoszą się także do tego ulr

+1

Po wypróbowaniu obu podejść Najbardziej byłem zadowolony z '@ PreAuthorize'. Dla każdego, kto się na to natknął, zabezpieczenie ciała wymagającego było dla mnie dość skomplikowane i mogłem połączyć coś z niektórymi usługami. EL zmienia się nieznacznie podczas wywoływania instancji komponentu bean. Przykład: '@PreAuthorize (" @ decision.isOK (# entry.blog.id, principal) ")' –

+1

Cieszę się, że pomogło :) '@ PreAuthorize' jest właśnie do tego celu, podczas gdy @Aspect jest bardziej ogólny:) – Elbek

+0

Parametry metody odwoływania ze Spring-EL w @PreAuthorize powinny być poprzedzone ostrym '' '' '' '' '. '' '' @PreAuthorize ("Decision.isOK (#entry, #principal)") '' '' zamiast '' '' @PreAuthorize ("Decision.isOK (entry, principal)") '' ''. –

Powiązane problemy