wake-up-neo.net

Spring Security, Method Security Annotation (@Secured) funktioniert nicht (Java-Konfiguration)

Ich versuche, eine Methodensicherheitsanmerkung unter Verwendung von @Secured ("ADMIN") einzurichten (ohne XML, nur Java-Konfiguration, Spring Boot). Der Zugriff über Rollen funktioniert jedoch nicht.

Sicherheitskonfiguration:

@Configuration
@EnableWebSecurity
public class AppSecurityConfiguration extends WebSecurityConfigurerAdapter{

.....

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/api/**").fullyAuthenticated().and()
                .addFilterBefore(tokenAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
    }

.....

}

Ich möchte den Zugriff auf die Methode des Controllers beschränken:

@RestController
@RequestMapping("/api/groups")
public class GroupController {

    @Autowired
    private GroupService groupService;

    @Secured("ADMIN")
    @RequestMapping
    public List<Group> list() {
        return groupService.findAll();
    }

}

Beschränken Sie den Zugriff durch die URL mit:

.antMatchers("/api/**").hasAuthority("ADMIN")

Vielleicht habe ich vergessen zu spezifizieren, dass ich mich auf Rollen beschränken möchte?

UPD: Nach den Regeln muss Auf welcher Ebene @PreAuthorize("hasRole('ADMIN')") in der Controller-Ebene oder in der Service-Schicht sein?

13
silverhawk

Dieses Problem wurde gelöst.

Ich füge @EnableGlobalMethodSecurity(prePostEnabled = true) hinzu

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class AppSecurityConfiguration extends WebSecurityConfigurerAdapter{
}

Und im Controller habe ich @Secured("ADMIN") in @PreAuthorize("hasRole('ADMIN')") geändert.

1
silverhawk

Bitte fügen Sie dies hinzu 

@EnableGlobalMethodSecurity(securedEnabled = true)

Dieses Element wird verwendet, um annotationsbasierte Sicherheit in Ihrer Anwendung zu aktivieren (durch Festlegen der entsprechenden Attribute für das Element), und um Sicherheits-Pointcut-Deklarationen zu gruppieren, die im gesamten Anwendungskontext speziell für @Secured..__ angewendet werden Code sollte so aussehen

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class AppSecurityConfiguration extends WebSecurityConfigurerAdapter{..
24
Mudassar

Es gibt viele Gründe, warum die Methodensicherheit auf einem Controller nicht funktioniert.

Erstens, weil es im Spring Security-Handbuch nie als Beispiel angeführt wird ... Scherz, aber es kann schwierig sein, Spring-Werkzeuge dort zu nehmen, wo sie nicht hingehören.

Im Ernstfall sollten Sie die Methodensicherheit aktivieren, wie bereits von @Mudassar gesagt. Das Handbuch sagt:

Wir können annotationsbasierte Sicherheit mit der @EnableGlobalMethodSecurity-Annotation für jede @Configuration-Instanz aktivieren. Die folgende würde beispielsweise die @Secured-Annotation von Spring Security aktivieren.

@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true)
public class MethodSecurityConfig {
   // ...
}

Beachten Sie, dass Mudassars Antwort bis hier richtig ist.

Die Methodensicherheit basiert jedoch auf AOP, das standardmäßig JDK-Proxying auf Interfaces verwendet. Aus diesem Grund wenden alle Beispiele die Methodensicherheit auf der Service-Schicht an, da die Service-Klassen normalerweise als Schnittstellen in Controller eingefügt werden.

Sie können es natürlich auf Controller-Ebene verwenden, aber:

  • alle Ihre Controller implementieren Schnittstellen für Sie, alle @Secured-kommentierten Methoden
  • oder Sie müssen zum Klassen-Proxying wechseln

Die Regel, die ich zu befolgen versuche, lautet:

  • wenn ich eine URL sichern möchte, halte ich mich an HTTPSecurity
  • wenn ich einen feineren Zugriff zulassen muss, füge ich Sicherheit auf Serviceebene hinzu
12
Serge Ballesta

Ich weiß, dass dieser Thread ziemlich alt ist, und meine Antwort spielt auf Teile der Antworten verschiedener Leute in diesem Thread an; Hier ist jedoch eine Liste mit einer Liste von Fallstricken und Antworten:

  1. Wenn Sie @Secured verwenden, lautet der Rollenname (z. B.) ADMIN. Dies bedeutet eine Annotation von @Secured ("ROLE_ADMIN").
  2. WebSecurityConfigurerAdapter muss über @EnableGlobalMethodSecurity verfügen (protectedEnabled = true)
  3. Stellen Sie, wie bei den meisten Spring-Proxies, sicher, dass die Klasse und die gesicherten Methoden in keiner Weise final sind. Für Kotlin bedeutet dies, dass sowohl jede Methode als auch die Klasse "offen" ist.
  4. Wenn die Klasse und ihre Methoden virtuell sind ("offen"), besteht keine implizite Notwendigkeit für eine Schnittstelle.

Hier ist ein Teil eines funktionierenden Kotlin-Beispiels:

@RestController
@RequestMapping("api/v1")

    open class DiagnosticsController {
        @Autowired
        lateinit var systemDao : SystemDao

        @RequestMapping("ping", method = arrayOf(RequestMethod.GET))
        @Secured("ROLE_ADMIN")
        open fun ping(request : HttpServletRequest, response: HttpServletResponse) : String { ... 
    }

und

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
open class WebSecurityConfig : WebSecurityConfigurerAdapter() {

Grüße

8
user1210708

Sie müssen @secured (ROLE_ADMIN) anstelle von @secured (ADMIN) verwenden. Sie müssen "ROLE_" vor Ihrem Rollennamen schreiben. Im Folgenden finden Sie das Beispiel, das sicherstellt, dass nur ein Benutzer mit Administratorrolle auf die list () -Methode zugreifen kann.

@RestController
@RequestMapping("/api/groups")
public class GroupController {

    @Autowired
    private GroupService groupService;

    @Secured("ROLE_ADMIN")
    @RequestMapping
    public List<Group> list() {
        return groupService.findAll();
    }

}
1
Sadiq Ali

Ich möchte meine Entscheidung teilen, vielleicht wird es hilfreich sein.

Gebrauchte spring mvc + spring security , version 4.2.9.RELEASE

Zum Beispiel habe ich einen Dienst mit der Methode @Secured 

@Secured("ACTION_USER_LIST_VIEW")
List<User> getUsersList();

Aber es hat nicht funktioniert, weil GlobalMethodSecurityConfiguration eine inside-Methode hat.

protected AccessDecisionManager accessDecisionManager()

wobei new RoleVoter() mit dem Standard rolePrefix = "ROLE_";initialisiert wurde (dies macht es unmöglich, Beans zu verwenden, um Ihren rolePrefix zu setzen), die uns nicht funktionierende Annotationen geben, weil RoleVoter Annotationswert erwartet, der mit 'ROLE_' beginnt.

Um dieses Problem zu beheben, überschreibe ich GlobalMethodSecurityConfiguration so

@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true)
public class AppMethodSecurityConfiguration extends GlobalMethodSecurityConfiguration {
    @Override
    protected AccessDecisionManager accessDecisionManager() {
        List<AccessDecisionVoter<? extends Object>> decisionVoters = new ArrayList<>();
        ExpressionBasedPreInvocationAdvice expressionAdvice = new ExpressionBasedPreInvocationAdvice();
        expressionAdvice.setExpressionHandler(getExpressionHandler());
        decisionVoters.add(getRoleVoter());
        decisionVoters.add(new AuthenticatedVoter());
        return new AffirmativeBased(decisionVoters);
    }

    private RoleVoter getRoleVoter() {
        RoleVoter e = new RoleVoter();
        e.setRolePrefix("");
        return e;
    }
}
0
Igor

Möglicherweise sollten Sie Ihre AppSecurityConfiguration im selben Kontext wie WebMvcConfig registrieren (wodurch WebMvcConfigurerAdapter erweitert wird).

AnnotationConfigWebApplicationContext mvcContext = new AnnotationConfigWebApplicationContext();      
mvcContext.register(WebMvcConfig.class, SecurityConfig.class);
0
digz6666