MongoDB
 sql >> база данни >  >> NoSQL >> MongoDB

Удостоверяване с Spring Security и MongoDB

Просто е трудно да се постигне истина, видимост в реално време в работещ автент поток.

Части от процеса могат да бъдат напълно скрити от нас; ако пълният процес на упълномощаване изисква пренасочване от отдалечен производствен сървър на OAuth, тогава всяко усилие за отстраняване на грешки трябва да премине през производствения сървър.

Практически е невъзможно това да се отстрани локално. Няма начин да се възпроизведе точното състояние и няма начин да се провери какво всъщност се случва под капака. Не е идеално.

Познавайки тези видове предизвикателства, ние изградихме Lightrun – инструмент за отстраняване на грешки в производството в реално време – за да ви позволим да разберете сложни потоци с информация на ниво код. Добавете регистрационни файлове, правете моментни снимки (виртуални точки на прекъсване) и показатели на инструмента без отдалечен дебъгер, без да спирате работещата услуга и най-важното - в реално време и без странични ефекти .

Научете повече с този 5-минутен урок фокусиран върху отстраняване на грешки на тези видове сценарии с помощта на Lightrun:

>> Отстраняване на грешки при удостоверяване и оторизация с помощта на Lightrun

1. Общ преглед

Spring Security предлага различни системи за удостоверяване, като например чрез база данни и UserDetailService .

Вместо да използваме слой за постоянство на JPA, може да искаме да използваме например хранилище MongoDB. В този урок ще видим как да удостоверим потребител с помощта на Spring Security и MongoDB.

2. Spring Security Authentication с MongoDB

Подобно на използването на JPA хранилище, можем да използваме хранилище MongoDB . Трябва обаче да зададем различна конфигурация, за да я използваме.

2.1. Зависимости на Maven

За този урок ще използваме Embedded MongoDB . Въпреки това, екземпляр на MongoDB и Testcontainer могат да бъдат валидни опции за производствена среда. Първо, нека добавим spring-boot-starter-data-mongodb и de.flapdoodle.embed.mongo зависимости:

<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. Конфигурация

След като зададем зависимости, можем да създадем нашата конфигурация:

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

Също така трябва да конфигурираме нашия AuthenticationManager с, например, HTTP основно удостоверяване:

@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. Потребителски домейн и хранилище

Първо, нека дефинираме прост потребител с роли за нашето удостоверяване. Ще го накараме да приложи Подробности за потребителя интерфейс за повторно използване на общите методи на Принципал обект:

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

Сега, когато имаме нашия потребител, нека дефинираме просто хранилище:

public interface UserRepository extends MongoRepository<User, String> {

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

2.4. Услуга за удостоверяване

Накрая, нека внедрим нашата UserDetailService за да извлечете потребител и да проверите дали е удостоверена :

@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. Тествайте удостоверяване

За да тестваме нашето приложение, нека дефинираме прост контролер. Като пример сме дефинирали две различни роли за тестване на удостоверяване и оторизация за конкретни крайни точки:

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

}

Нека да приключим всичко с Spring Boot Test, за да проверим дали нашата автентификация работи. Както виждаме, очакваме код 401 за някой, който предоставя невалидни идентификационни данни или който не съществува в нашата система :

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. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. MongoDB, Mongoose:Как да намеря поддокумент в намерен документ?

  2. Мигриране на MongoDB към DynamoDB, част 2

  3. ABCs на NestJS:Ръководство за начинаещи с MongoDB (Mongoose).

  4. Запитване на вградени обекти в Mongoid/rails 3 (по-ниски от, Min оператори и сортиране)

  5. Първи стъпки с Python и MongoDB