В предыдущем посте мы настраивали весеннюю конфигурацию безопасности, предоставляя настраиваемые запросы для пользователя и получения полномочий из базы данных SQL.
В настоящее время многие современные приложения используют базы данных NoSQL. Безопасность Spring не поставляется с готовым решением для баз данных NoSQL.
В этих случаях нам необходимо предоставить решение путем реализации пользовательского UserDetailsService.
Мы будем использовать базу данных MongoDB для этого примера. Я буду использовать образ докера , однако настроить базу данных mongodb так же просто, загрузив ее с официального сайта .
Вот некоторые команды для начала работы с docker и mongodb (не стесняйтесь их игнорировать, если вы не используете docker)
|
01
02
03
04
05
06
07
08
09
10
|
#pull the mongo imagedocker pull mongo#create a mongo containerdocker run --name some-mongo -d mongo#get the docker container iddocker ps#get the containers ipdocker inspect --format '{{ .NetworkSettings.IPAddress }}' $CID#connection using the ip retrievedmongo $mongodb_container_ip |
Затем мы напишем простой скрипт инициализации с именем createuser.js. Сценарий создает документ, содержащий информацию о пользователе, такую как имя пользователя, пароль и права доступа.
|
1
2
|
use springsecuritydb.users.insert({"name":"John","surname":"doe","email":"john@doe.com","password":"cleartextpass","authorities":["user","admin"]}) |
Мы будем использовать Mongo Cli для его выполнения.
|
1
|
mongo 172.17.0.2:27017 < createuser.js |
Чтобы использовать Spring Security с mongodb, нам нужно получить информацию о пользователях из коллекции пользователей.
Первым шагом является добавление зависимостей mongodb в наш файл gradle, включая драйвер mongodb. Обратите внимание, что мы будем использовать профиль под названием «customuserdetails».
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
group 'com.gkatzioura'version '1.0-SNAPSHOT'buildscript { repositories { mavenCentral() } dependencies { classpath("org.springframework.boot:spring-boot-gradle-plugin:1.4.0.RELEASE") }}apply plugin: 'java'apply plugin: 'idea'apply plugin: 'spring-boot'sourceCompatibility = 1.8repositories { mavenCentral()}dependencies { compile("org.springframework.boot:spring-boot-starter-web") compile("org.thymeleaf:thymeleaf-spring4") compile("org.springframework.boot:spring-boot-starter-security") compile("org.mongodb:mongo-java-driver:1.3") compile("org.slf4j:slf4j-api:1.6.6") compile("ch.qos.logback:logback-core:1.1.7") compile("ch.qos.logback:logback-classic:1.1.7") testCompile "junit:junit:4.11"}bootRun { systemProperty "spring.profiles.active", "customuserdetails"} |
Затем мы создадим компонент подключения mongodb.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
package com.gkatzioura.spring.security.config;import com.mongodb.Mongo;import com.mongodb.MongoClient;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Profile;/** * Created by gkatzioura on 9/27/16. */@Configuration@Profile("customuserdetails")public class MongoConfiguration { @Bean public MongoClient createConnection() { //You should put your mongo ip here return new MongoClient("172.17.0.2:27017"); }} |
Затем мы создадим пользовательский объект сведений о пользователе.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
package com.gkatzioura.spring.security.model;import org.springframework.security.core.GrantedAuthority;import org.springframework.security.core.authority.AuthorityUtils;import org.springframework.security.core.userdetails.UserDetails;import java.util.Collection;import java.util.List;/** * Created by gkatzioura on 9/27/16. */public class MongoUserDetails implements UserDetails{ private String username; private String password; private List<GrantedAuthority> grantedAuthorities; public MongoUserDetails(String username,String password,String[] authorities) { this.username = username; this.password = password; this.grantedAuthorities = AuthorityUtils.createAuthorityList(authorities); } @Override public Collection<? extends GrantedAuthority> getAuthorities() { return grantedAuthorities; } @Override public String getPassword() { return password; } @Override public String getUsername() { return username; } @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { return true; }} |
Следующим шагом мы добавим пользовательский UserDetailsService, получающий информацию о пользователе через базу данных mongodb.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
package com.gkatzioura.spring.security.service;import com.gkatzioura.spring.security.model.MongoUserDetails;import com.mongodb.MongoClient;import com.mongodb.client.MongoCollection;import com.mongodb.client.MongoDatabase;import com.mongodb.client.model.Filters;import org.bson.Document;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.security.core.userdetails.UserDetails;import org.springframework.security.core.userdetails.UserDetailsService;import org.springframework.security.core.userdetails.UsernameNotFoundException;import org.springframework.stereotype.Service;import java.util.List;/** * Created by gkatzioura on 9/27/16. */public class CustomerUserDetailsService implements UserDetailsService { @Autowired private MongoClient mongoClient; @Override public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException { MongoDatabase database = mongoClient.getDatabase("springsecurity"); MongoCollection<Document> collection = database.getCollection("users"); Document document = collection.find(Filters.eq("email",email)).first(); if(document!=null) { String name = document.getString("name"); String surname = document.getString("surname"); String password = document.getString("password"); List<String> authorities = (List<String>) document.get("authorities"); MongoUserDetails mongoUserDetails = new MongoUserDetails(email,password,authorities.toArray(new String[authorities.size()])); return mongoUserDetails; } return null; }} |
Последний шаг — предоставить весеннюю конфигурацию безопасности, используя пользовательский UserDetailsService, который мы реализовали ранее.
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
package com.gkatzioura.spring.security.config;import com.gkatzioura.spring.security.service.CustomerUserDetailsService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Profile;import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;import org.springframework.security.config.annotation.web.builders.HttpSecurity;import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;import org.springframework.security.core.userdetails.UserDetailsService;/** * Created by gkatzioura on 9/27/16. */@EnableWebSecurity@Profile("customuserdetails")public class CustomUserDetailsSecurityConfig extends WebSecurityConfigurerAdapter { @Bean public UserDetailsService mongoUserDetails() { return new CustomerUserDetailsService(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { UserDetailsService userDetailsService = mongoUserDetails(); auth.userDetailsService(userDetailsService); } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/public").permitAll() .anyRequest().authenticated() .and() .formLogin() .permitAll() .and() .logout() .permitAll(); }} |
Чтобы запустить проблему приложения
|
1
|
gradle bootRun |
Вы можете найти исходный код на GitHub
| Ссылка: | Spring загружается с помощью Spring Security и NoSQL от нашего партнера по JCG Эммануила Гкатзиураса в блоге gkatzioura . |