Я выполняю аналогичный проект и думаю, что могу помочь вам с некоторыми рекомендациями.
OAuth2 - это авторизация и аутентификация безопасности на основе токенов, которые мы можем разбить на четыре компонента:
- Защищенный ресурс (доступ к нему может получить только аутентифицированный пользователь, имеющий соответствующую авторизацию)
- Владелец ресурса (определяет, какое приложение может вызывать свою службу, какому пользователю разрешен доступ к службе и что он может do)
- Приложение (приложение, которое будет вызывать службу от имени пользователей)
- Служба аутентификации OAuth2 (находится между приложением и защищенным ресурсом)
В вашем случае защищенный ресурс - это монолит, который вы хотите разрушить в архитектуре микросервисов.
- Первое, что вам нужно сделать, это создать службу авторизации.
Создать проект SpringCloud из Spring Intilizr, убедитесь, что нижеприведенные зависимости присутствует:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-security</artifactId>
</dependency>
После этого в основной класс сервиса oauth2 необходимо добавить две аннотации. @EnableResourceServer
используется, чтобы сообщить микросервису, что это защищенный ресурс. Я объясню ниже, зачем это нужно. @EnableAuthorizationServer
сообщит Spring Cloud, что это сервис, который будет использоваться как OAuth2Service. Ниже приведен фрагмент кода:
@SpringBootApplication
@EnableResourceServer
@EnableAuthorizationServer
public class Oauth2ServerApplication {
public static void main(String[] args) {
SpringApplication.run(Oauth2ServerApplication.class, args);
}
}
Мы создаем конечную точку, которая будет предоставлять информацию о пользователе. Эта конечная точка будет вызываться другими службами. По этой причине мы пометили это приложение @EnableResourceServer
. Ниже расположена конечная точка отдыха, которая возвращает информацию о пользователе:
@RestController
@RequestMapping("/user")
public class UserRestController {
@GetMapping(produces="application/json")
public Map<String,Object> getUser(OAuth2Authentication user){
Map<String,Object> userInfo = new HashMap<>();
userInfo.put("user",user.getUserAuthentication().getPrincipal());
userInfo.put("authorities", user.getUserAuthentication().getAuthorities());
return userInfo;
}
}
Теперь вы зарегистрируете приложение в сервисе oauth2. Вы определите приложение, которое будет обращаться к защищенному ресурсу. Вы создадите класс конфигурации, который определит, какое приложение может использовать ваш сервис.
@Configuration
public class OAuth2Config extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
OAuth2ConfigParameters oauth2ConfigParameters;
@Bean
public OAuth2ConfigParameters oAuth2ConfigParameters() {
return new OAuth2ConfigParameters();
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService);
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("your application")
.secret("your password")
.authorizedGrantTypes( "refresh_token","password","client_credentials")
.scopes("webclient","mobileclient");
}
}
Вам необходимо определить, какие пользователи и роли для приложения. Это знакомо, если вы сделали безопасность с SpringBoot. Проверьте фрагмент ниже:
@Configuration
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
@Bean
public UserDetailsService userDetailsServiceBean() throws Exception {
return super.userDetailsServiceBean();
}
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("you user")
.password(passwordEncoder().encode("your password"))
.roles("your role");
}
}
В конце уточните у почтальона, можете ли вы получить токен из службы oauth2.
HttpMethod : POST, URL : http://localhost: порт приложения / oauth / токен
Тип авторизации : Basi c, имя пользователя : клиент id, пароль : секрет клиента
Тело : данные формы,
грант: пароль
область действия: веб-клиент
имя пользователя: ваше имя пользователя
пароль: ваш пароль
После получения токена проверьте, можете ли вы получить доступ к этому токену по URL-адресу конечной точки, которой вы предоставляете информацию о пользователе.
HttpMethod : Получить, URL : localhost: порт приложения / пользователь
Авторизация : Носитель, Токен : генерируется токен
- Во-вторых, защита вашего старого монолита, к которому будет обращаться сервер шлюза. Помните, что ваш старый монолит является защитой cted resource.
Сначала вам нужно добавить файлы Spring Security и OAuth2 в службу, которую вы пытаетесь защитить.
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
</dependency>
Далее в application.yml монолита, который мы настроить точку обслуживания вашего сервиса oauth2. Это сделано потому, что монолит является защищенной службой, и каждый раз, когда приходит запрос, вы хотите проверить, является ли токен запроса действительным.
security:
oauth2:
resource:
userInfoUri: http://localhost:oauth2-app-port/auth/user
После этого не забудьте добавить @EnableResourceServer
что делает монолит защищенным ресурсом.
@SpringBootApplication
@EnableResourceServer
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
После этого мы указываем желаемое ограничение. Ниже я привел пример, ограничивающий доступ только для аутентифицированных пользователей.
@Configuration
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated();
}
}
Ваш пользователь аутентифицирован из OAuth сервис и имеет сгенерированный токен. С созданным токеном отправьте запрос на монолит через сервер шлюза. Шлюз пытается получить доступ к монолиту, распространяя токен, полученный из запроса. Монолит проверяет, является ли токен действительным.
Ниже приведена связь моей микросервисной архитектуры с сервером шлюза zuul и сервером oauth2: https://github.com/rshtishi/payroll. Вы можете проверить это, если хотите увидеть больше деталей.