Spring Security: Authentication & Permissions

RezaScript

Bekanntes Mitglied
Hallo,

ich folge gerade ein Tutorial bezüglich Spring Security und verstehe irgendwie nur Bahnhof.

Java:
@Configuration
@EnableWebSecurity
public class ApplicationSecurityConfig  {
    private final PasswordEncoder passwordEncoder;

    @Autowired
    public ApplicationSecurityConfig(PasswordEncoder passwordEncoder) {
        this.passwordEncoder = passwordEncoder;
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .authorizeRequests()
                .antMatchers("/", "index", "/css/*", "js/*").permitAll()
                .antMatchers("/api/**").hasRole(STUDENT.name())
                .antMatchers(HttpMethod.DELETE, "management/api/**").hasRole(ApplicationUserPermission.COURSE_WRITE.name())
                .antMatchers(HttpMethod.POST, "management/api/**").hasRole(ApplicationUserPermission.COURSE_WRITE.name())
                .antMatchers(HttpMethod.PUT, "management/api/**").hasRole(ApplicationUserPermission.COURSE_WRITE.name())
                .antMatchers(HttpMethod.GET, "management/api/**").hasAnyRole(ADMIN.name(), ADMINTRAINEE.name())
                .anyRequest()
                .authenticated()
                .and()
                .httpBasic();
        return http.build();
    }

    @Bean
    public InMemoryUserDetailsManager userDetailsManager() {
        var annaSmith = User.builder()
                .username("annasmith")
                .password(passwordEncoder.encode("password"))
                //.roles(STUDENT.name())
                .authorities(STUDENT.getGrantedAuthorities())
                .build();

        var linda = User.builder()
                .username("linda")
                .password(passwordEncoder.encode("lindapass"))
                //.roles(ApplicationUserRole.ADMIN.name())
                .authorities(ApplicationUserRole.ADMIN.getGrantedAuthorities())
                .build();

        var tom = User.builder()
                .username("tom")
                .password(passwordEncoder.encode("tompass"))
                //.roles(ApplicationUserRole.ADMINTRAINEE.name())
                .authorities(ADMINTRAINEE.getGrantedAuthorities())
                .build();

        return new InMemoryUserDetailsManager(annaSmith, linda, tom);
    }
}

Java:
public enum ApplicationUserRole {
    STUDENT(Sets.newHashSet()),
    ADMIN(Sets.newHashSet(COURSE_READ, COURSE_WRITE, STUDENT_READ, STUDENT_WRITE)),
    ADMINTRAINEE(Sets.newHashSet(COURSE_READ, STUDENT_READ));;

    private final Set<ApplicationUserPermission> permissions;

    ApplicationUserRole(Set<ApplicationUserPermission> permissions) {
        this.permissions = permissions;
    }

    public Set<ApplicationUserPermission> getPermissions() {
        return permissions;
    }

    public Set<SimpleGrantedAuthority> getGrantedAuthorities() {
        Set<SimpleGrantedAuthority> permissions = getPermissions().stream()
                .map(permission -> new SimpleGrantedAuthority(permission.getPermission()))
                .collect(Collectors.toSet());

        permissions.add(new SimpleGrantedAuthority("ROLE_" + this.name()));
        return permissions;
    }
}

Java:
public enum ApplicationUserPermission {
    STUDENT_READ("student:read"),
    STUDENT_WRITE("student:write"),
    COURSE_READ("course:read"),
    COURSE_WRITE("course:write");

    private final String permission;

    ApplicationUserPermission(String permission) {
        this.permission = permission;
    }

    public String getPermission() {
        return permission;
    }
}

Also ... was ich nicht verstehe ist vor allem die Methode getGrantedAuthorities(). Fangen wir mal mit getPermissions() an. Der Constructor hat einen Parameter. Ich sehe nirgends, dass ich diesen Constructor mit einen Parameter aufrufe.

Und wozu braucht es
Java:
.map(permission -> new SimpleGrantedAuthority(permission.getPermission()))
.collect(Collectors.toSet());
?

Offenbar fügt diese Methode zunächst eine Autorität hinzu, bevor sie eine Liste ausgibt. Aber was soll denn this.name() sein?

Warum muss es .authorities(ApplicationUserRole.ADMIN.getGrantedAuthorities()) sein? Warum nicht einfach .authorities(ApplicationUserRole.ADMIN)? In ADMIN sind ja alle Permissions schon definiert.

Wäre froh, wenn mich jemand etwas aufklären würde.
 
Zuletzt bearbeitet:
Warum kann ich meinen Beitrag nicht editieren?

Jedenfalls kann die Konfiguration dadurch ersetzt werden:

Java:
@Configuration
@EnableWebSecurity
public class ApplicationSecurityConfig  {
    private final PasswordEncoder passwordEncoder;

    @Autowired
    public ApplicationSecurityConfig(PasswordEncoder passwordEncoder) {
        this.passwordEncoder = passwordEncoder;
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .authorizeRequests()
                .antMatchers("/", "index", "/css/*", "js/*").permitAll()
                .antMatchers("/api/**").hasRole(STUDENT.name())
                .antMatchers(HttpMethod.DELETE, "/management/api/**").hasAuthority(ApplicationUserPermission.COURSE_WRITE.getPermission())
                .antMatchers(HttpMethod.POST, "/management/api/**").hasAuthority(ApplicationUserPermission.COURSE_WRITE.getPermission())
                .antMatchers(HttpMethod.PUT, "/management/api/**").hasAuthority(ApplicationUserPermission.COURSE_WRITE.getPermission())
                .antMatchers(HttpMethod.GET, "/management/api/**").hasAnyRole(ADMIN.name(), ADMINTRAINEE.name())
                .anyRequest()
                .authenticated()
                .and()
                .httpBasic();
        return http.build();
    }

    @Bean
    public InMemoryUserDetailsManager userDetailsManager() {
        var annaSmith = User.builder()
                .username("annasmith")
                .password(passwordEncoder.encode("password"))
                //.roles(STUDENT.name())
                .authorities(STUDENT.getGrantedAuthorities())
                .build();

        var linda = User.builder()
                .username("linda")
                .password(passwordEncoder.encode("pass"))
                //.roles(ApplicationUserRole.ADMIN.name())
                .authorities(ADMIN.getGrantedAuthorities())
                .build();

        var tom = User.builder()
                .username("tom")
                .password(passwordEncoder.encode("pass"))
                //.roles(ApplicationUserRole.ADMINTRAINEE.name())
                .authorities(ADMINTRAINEE.getGrantedAuthorities())
                .build();

        return new InMemoryUserDetailsManager(annaSmith, linda, tom);
    }
}
Hab's getestet und funktioniert gut.
 
Also ... was ich nicht verstehe ist vor allem die Methode getGrantedAuthorities(). Fangen wir mal mit getPermissions() an. Der Constructor hat einen Parameter. Ich sehe nirgends, dass ich diesen Constructor mit einen Parameter aufrufe.
Ich verstehe die Frage nicht. Die Verwendung des/der Constructor's in den Enums ist doch offensichtlich!
Java:
..
    STUDENT(Sets.newHashSet()),
    ADMIN(Sets.newHashSet(COURSE_READ, COURSE_WRITE, STUDENT_READ, STUDENT_WRITE)),
    ADMINTRAINEE(Sets.newHashSet(COURSE_READ, STUDENT_READ));;

...
    STUDENT_READ("student:read"),
    STUDENT_WRITE("student:write"),
    COURSE_READ("course:read"),
    COURSE_WRITE("course:write");
 
Wie bekomme ich denn in ApplicationUserRole die Pemissions?

Der Constructor ist ja
Java:
ApplicationUserRole(Set<ApplicationUserPermission> permissions) {
    this.permissions = permissions;
}

D.h. ich müsste ihn ja mit einem Parameter, also ApplicationUserRole(...), aufrufen. Wie weiss also, dass getPermissions() was der Wert von permissions ist?
 

Zurück
Oben