sql >> Database teknologi >  >> NoSQL >> MongoDB

Autentificering med Spring Security og MongoDB

Det er simpelthen svært at få sandheden, realtidssynlighed i en kørende godkendelse flow.

Dele af processen kan være fuldstændig skjult for os; hvis den komplette godkendelsesproces kræver en omdirigering fra en ekstern OAuth-produktionsserver, så skal enhver fejlretningsindsats gå gennem produktionsserveren.

Det er praktisk talt umuligt at foretage fejlfinding lokalt. Der er ingen måde at gengive den nøjagtige tilstand og ingen måde at inspicere, hvad der rent faktisk sker under emhætten. Ikke ideelt.

Ved at kende disse typer udfordringer byggede vi Lightrun - et produktionsfejlfindingsværktøj i realtid - for at give dig mulighed for at forstå komplicerede flows med information på kodeniveau. Tilføj logfiler, tag snapshots (virtuelle brudpunkter) og instrumentmålinger uden en fjernfejlfinder, uden at stoppe den kørende tjeneste, og vigtigst af alt - i realtid og uden bivirkninger .

Få mere at vide med dette 5-minutters selvstudie fokuseret på fejlretning af disse slags scenarier ved hjælp af Lightrun:

>> Fejlretning af godkendelse og autorisation ved hjælp af Lightrun

1. Oversigt

Spring Security tilbyder forskellige godkendelsessystemer, såsom via en database og UserDetailService .

I stedet for at bruge et JPA-vedholdenhedslag vil vi måske også bruge for eksempel et MongoDB-lager. I denne vejledning vil vi se, hvordan man godkender en bruger ved hjælp af Spring Security og MongoDB.

2. Spring Security Authentication med MongoDB

I lighed med at bruge et JPA-lager, kan vi bruge et MongoDB-lager . Vi skal dog indstille en anden konfiguration for at kunne bruge den.

2.1. Maven afhængigheder

Til denne vejledning skal vi bruge Embedded MongoDB . Dog en MongoDB-instans og Testcontainer kunne være gyldige muligheder for et produktionsmiljø. Lad os først tilføje spring-boot-starter-data-mongodb og de.flapdoodle.embed.mongo afhængigheder:

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
    <groupId>de.flapdoodle.embed</groupId>
    <artifactId>de.flapdoodle.embed.mongo</artifactId>
    <version>3.3.1</version>
</dependency>

2.2. Konfiguration

Når vi har indstillet afhængigheder, kan vi oprette vores konfiguration:

@Configuration
public class MongoConfig {

    private static final String CONNECTION_STRING = "mongodb://%s:%d";
    private static final String HOST = "localhost";

    @Bean
    public MongoTemplate mongoTemplate() throws Exception {

        int randomPort = SocketUtils.findAvailableTcpPort();

        ImmutableMongodConfig mongoDbConfig = MongodConfig.builder()
          .version(Version.Main.PRODUCTION)
          .net(new Net(HOST, randomPort, Network.localhostIsIPv6()))
          .build();

        MongodStarter starter = MongodStarter.getDefaultInstance();
        MongodExecutable mongodExecutable = starter.prepare(mongoDbConfig);
        mongodExecutable.start();
        return new MongoTemplate(MongoClients.create(String.format(CONNECTION_STRING, HOST, randomPort)), "mongo_auth");
    }
}

Vi skal også konfigurere vores AuthenticationManager med for eksempel en HTTP grundlæggende godkendelse:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, jsr250Enabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    // ...
    public SecurityConfig(UserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

    @Bean
    public AuthenticationManager customAuthenticationManager() throws Exception {
        return authenticationManager();
    }

    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(@Autowired AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService)
          .passwordEncoder(bCryptPasswordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf()
          .disable()
          .authorizeRequests()
          .and()
          .httpBasic()
          .and()
          .authorizeRequests()
          .anyRequest()
          .permitAll()
          .and()
          .sessionManagement()
          .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }
}

2.3. Brugerdomæne og -lager

Lad os først definere en simpel bruger med roller til vores godkendelse. Vi får det til at implementere Brugeroplysningerne grænseflade til at genbruge commons-metoder for en Rektor objekt:

@Document
public class User implements UserDetails {
    private @MongoId ObjectId id;
    private String username;
    private String password;
    private Set<UserRole> userRoles;
    // getters and setters
}

Nu hvor vi har vores bruger, lad os definere et simpelt lager:

public interface UserRepository extends MongoRepository<User, String> {

    @Query("{username:'?0'}")
    User findUserByUsername(String username);
}

2.4. Autentificeringstjeneste

Lad os endelig implementere vores UserDetailService for at hente en bruger og kontrollere, om den er godkendt :

@Service
public class MongoAuthUserDetailService implements UserDetailsService {
    // ...
    @Override
    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {

        com.baeldung.mongoauth.domain.User user = userRepository.findUserByUsername(userName);

        Set<GrantedAuthority> grantedAuthorities = new HashSet<>();

        user.getAuthorities()
          .forEach(role -> {
              grantedAuthorities.add(new SimpleGrantedAuthority(role.getRole()
                 .getName()));
          });

        return new User(user.getUsername(), user.getPassword(), grantedAuthorities);
    }

}

2.5. Test godkendelse

For at teste vores applikation, lad os definere en simpel controller. Som et eksempel har vi defineret to forskellige roller til at teste godkendelse og godkendelse for specifikke slutpunkter:

@RestController
public class ResourceController {

    @RolesAllowed("ROLE_ADMIN")
    @GetMapping("/admin")
    public String admin() {
        return "Hello Admin!";
    }

    @RolesAllowed({ "ROLE_ADMIN", "ROLE_USER" })
    @GetMapping("/user")
    public String user() {
        return "Hello User!";
    }

}

Lad os pakke det hele sammen i en Spring Boot Test for at kontrollere, om vores godkendelse virker. Som vi kan se, forventer vi en 401-kode til en person, der giver ugyldige legitimationsoplysninger, eller som ikke findes i vores system :

class MongoAuthApplicationTest {

    // set up

    @Test
    void givenUserCredentials_whenInvokeUserAuthorizedEndPoint_thenReturn200() throws Exception {
        mvc.perform(get("/user").with(httpBasic(USER_NAME, PASSWORD)))
          .andExpect(status().isOk());
    }

    @Test
    void givenUserNotExists_whenInvokeEndPoint_thenReturn401() throws Exception {
        mvc.perform(get("/user").with(httpBasic("not_existing_user", "password")))
          .andExpect(status().isUnauthorized());
    }

    @Test
    void givenUserExistsAndWrongPassword_whenInvokeEndPoint_thenReturn401() throws Exception {
        mvc.perform(get("/user").with(httpBasic(USER_NAME, "wrong_password")))
          .andExpect(status().isUnauthorized());
    }

    @Test
    void givenUserCredentials_whenInvokeAdminAuthorizedEndPoint_thenReturn403() throws Exception {
        mvc.perform(get("/admin").with(httpBasic(USER_NAME, PASSWORD)))
          .andExpect(status().isForbidden());
    }

    @Test
    void givenAdminCredentials_whenInvokeAdminAuthorizedEndPoint_thenReturn200() throws Exception {
        mvc.perform(get("/admin").with(httpBasic(ADMIN_NAME, PASSWORD)))
          .andExpect(status().isOk());

        mvc.perform(get("/user").with(httpBasic(ADMIN_NAME, PASSWORD)))
          .andExpect(status().isOk());
    }
}

  1. MongoDB:Hvordan opdaterer man flere dokumenter med en enkelt kommando?

  2. Find værdier, der ikke indeholder tal i SQL

  3. MongoDB / Meteor / Eksporter MONGO_URL til implementerede applikationer

  4. Sådan konfigurerer du Yii2 med Redis-konfiguration