sql >> Databasteknik >  >> NoSQL >> MongoDB

Autentisering med Spring Security och MongoDB

Det är helt enkelt svårt att få sant, synlighet i realtid i en körande autentisering flöde.

Delar av processen kan döljas helt för oss; om den fullständiga auktoriseringsprocessen kräver en omdirigering från en fjärransluten OAuth-produktionsserver, måste alla felsökningsåtgärder gå via produktionsservern.

Det är praktiskt taget omöjligt att felsöka detta lokalt. Det finns inget sätt att återskapa det exakta tillståndet och inget sätt att inspektera vad som faktiskt händer under huven. Inte idealiskt.

Vi känner till dessa typer av utmaningar och byggde Lightrun – ett produktionsfelsökningsverktyg i realtid – så att du kan förstå komplicerade flöden med information på kodnivå. Lägg till loggar, ta ögonblicksbilder (virtuella brytpunkter) och instrumentmätningar utan en fjärrfelsökning, utan att stoppa tjänsten som körs, och, viktigast av allt - i realtid och utan biverkningar .

Läs mer med denna 5-minuters självstudie fokuserat på att felsöka den här typen av scenarier med Lightrun:

>> Felsökning av autentisering och auktorisering med Lightrun

1. Översikt

Spring Security erbjuder olika autentiseringssystem, till exempel via en databas och UserDetailService .

Istället för att använda ett JPA-beständighetslager kanske vi också vill använda till exempel ett MongoDB-förråd. I den här handledningen kommer vi att se hur man autentiserar en användare med Spring Security och MongoDB.

2. Vårsäkerhetsautentisering med MongoDB

I likhet med att använda ett JPA-förråd kan vi använda ett MongoDB-förråd . Vi måste dock ställa in en annan konfiguration för att kunna använda den.

2.1. Maven beroenden

För den här handledningen kommer vi att använda Embedded MongoDB . Däremot en MongoDB-instans och Testcontainer kan vara giltiga alternativ för en produktionsmiljö. Låt oss först lägga till spring-boot-starter-data-mongodb och de.flapdoodle.embed.mongo beroenden:

<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 väl har ställt in beroenden kan vi skapa vår 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 måste också konfigurera vår AuthenticationManager med till exempel en grundläggande HTTP-autentisering:

@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. Användardomän och arkiv

Låt oss först definiera en enkel användare med roller för vår autentisering. Vi kommer att låta det implementera Användardetaljer gränssnitt för att återanvända commons-metoder för 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 när vi har vår användare, låt oss definiera ett enkelt arkiv:

public interface UserRepository extends MongoRepository<User, String> {

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

2.4. Autentiseringstjänst

Låt oss slutligen implementera vår UserDetailService för att hämta en användare och kontrollera om den är autentiserad :

@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. Testa autentisering

För att testa vår applikation, låt oss definiera en enkel kontroller. Som ett exempel har vi definierat två olika roller för att testa autentisering och auktorisering för specifika 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!";
    }

}

Låt oss avsluta det hela i ett Spring Boot Test för att kontrollera om vår autentisering fungerar. Som vi kan se, förväntar vi oss en 401-kod för någon som tillhandahåller ogiltiga referenser eller som inte finns i vårt 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. Mongo DB 4.0 Transaktioner med Mongoose &NodeJs, Express

  2. Hur man installerar Redis

  3. Stackfönstret visar ingen utdata vid felsökning av Redis Lua-skript med ZeroBrane

  4. Redis Keyspace Notifications med flushdb