Вчера Сонг Гэ и мои друзья говорили о режиме кода авторизации в OAuth 2. Я написал очень подробный кейс от начала до конца, чтобы поделиться с друзьями использованием режима кода авторизации.
Маленький партнер сказал, почему нет демо-кода для остальных трех режимов авторизации? Чтобы узнать, чтобы узнать полный набор! Нет, Сонг Гэ быстро разобрал коды трех других режимов авторизации для справки друзей.
Сегодняшний случай, я не пишу на пустом месте, мы вПредыдущая статьяДостаточно модифицировать код на основе кода.Если вы не читали предыдущие статьи этой серии, то рекомендуется сначала прочитать ее, иначе эта статья может быть не понята:
- Чтобы сделать OAuth2, который нельзя обойти микросервисами, Сонг Гэ также пришел поговорить с вами об этом.
- Этот случай написан, и вы боитесь, что не сможете понять процесс входа в систему OAuth2 с интервьюером?
Далее Songge напрямую загружает код.Я не буду повторять процесс различных режимов авторизации.Вы можете обратиться к этой серии.первая статья.
Кстати, исходный код этой статьи еще можно скачать в конце статьи.
1. Упрощенный режим
Для поддержки упрощенного режима это на самом деле очень просто.
Во-первых, мы добавляем следующую конфигурацию на сервер авторизации для поддержки упрощенного режима:
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("javaboy")
.secret(new BCryptPasswordEncoder().encode("123"))
.resourceIds("res1")
.authorizedGrantTypes("refresh_token","implicit")
.scopes("all")
.redirectUris("http://localhost:8082/index.html");
}
Обратите внимание, что нам нужно только добавить неявное значение в authorGrantTypes для поддержки упрощенного режима.
После завершения настройки перезапустите сервер авторизации.
Далее мы настраиваем сервер ресурсов. Поскольку в упрощенном режиме нет сервера, мы можем запрашивать данные на сервере ресурсов только через js, поэтому сервер ресурсов должен поддерживать междоменный доступ.Мы модифицируем следующие два места для поддержки междоменного доступа:
@RestController
@CrossOrigin(value = "*")
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "hello";
}
@GetMapping("/admin/hello")
public String admin() {
return "admin";
}
}
Сначала добавьте аннотацию @CrossOrigin в контроллер для поддержки междоменного взаимодействия, а затем настройте Spring Security для поддержки междоменного взаимодействия:
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/**").hasRole("admin")
.anyRequest().authenticated()
.and()
.cors();
}
После завершения настройки перезапустите пользовательский сервер.
Далее настраиваем стороннее приложение:
Сначала мы модифицируем страницу index.html:
<body>
你好,江南一点雨!
<a href="http://localhost:8080/oauth/authorize?client_id=javaboy&response_type=token&scope=all&redirect_uri=http://localhost:8082/index.html">第三方登录(简化模式)</a>
<div id="div1"></div>
<script>
var hash = window.location.hash;//提取出参数,类似这种格式#access_token=9fda1800-3b57-4d32-ad01-05ff700d44cc&token_type=bearer&expires_in=7199
if (hash && hash.length > 0) {
var params = hash.substring(1).split("&");
var token = params[0].split("=");//[access_token,9fda1800-3b57-4d32-ad01-05ff700d44cc]
$.ajax({
type: 'get',
headers: {
'Authorization': 'Bearer ' + token[1]
},
url: 'http://localhost:8081/admin/hello',
success: function (data) {
$("#div1").html(data)
}
})
}
</script>
</body>
Предыдущая гиперссылка остается без изменений, но мы меняем значение response_type на token, что означает, что код авторизации возвращается напрямую, а остальные параметры остаются без изменений.
Таким образом, когда пользователь успешно войдет в систему, он будет автоматически перенаправлен наhttp://localhost:8082/index.htmlстраницу и добавьте параметр привязки, как показано ниже:
http://localhost:8082/index.html#access_token=9fda1800-3b57-4d32-ad01-05ff700d44cc&token_type=bearer&expires_in=1940
Итак, далее мы извлекаем его в js#
Следующие параметры и дальнейший анализ значения access_token.
Со значением access_token мы отправляем Ajax-запрос, помещаем access_token в заголовок запроса и после успешного выполнения запроса помещаем запрошенные данные в div.
Это то, что мы называем упрощенным режимом.
После завершения настройки запустите клиентское приложение и получите доступhttp://localhost:8082/index.html
Страница протестирована, после авторизации пользователя происходит автоматическое перенаправление на страницу, эффект отображения следующий:
Полный код можно скачать в конце статьи.
2. Режим пароля
Режим пароля требует от пользователя непосредственного ввода имени пользователя и пароля в стороннем приложении для входа в систему. Давайте посмотрим.
Обратите внимание, что следующий код основан на режиме кода авторизации из предыдущей статьи.
Во-первых, измените auth-server для поддержки режима пароля:
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("javaboy")
.secret(new BCryptPasswordEncoder().encode("123"))
.resourceIds("res1")
.authorizedGrantTypes("password","refresh_token")
.scopes("all")
.redirectUris("http://localhost:8082/index.html");
}
Все остальное здесь без изменений, в основном режим пароля добавлен в authorGrantTypes.
Поскольку пользователю необходимо войти в систему после использования режима пароля, нам необходимо настроить AuthenticationManager или класс AuthorizationServer, конкретная конфигурация выглядит следующим образом:
@Autowired
AuthenticationManager authenticationManager;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.authenticationManager(authenticationManager)
.tokenServices(tokenServices());
}
Обратите внимание, что в режиме кода авторизации настроенные сервисы AuthorizationCodeServices больше не нужны, их заменили authenticationManager.
Итак, откуда берется этот экземпляр authenticationManager? Это нужно предусмотреть в конфигурации Spring Security, о чем Сон Гэ много раз говорил в предыдущей серии туториалов по Spring Security, и я не буду повторяться.Вот непосредственно код, а в SecurityConfig добавляется следующий код:
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
После завершения настройки перезапустите сервер авторизации.
Затем настройте client-app.Во-первых, мы добавляем функцию входа в систему и модифицируем index.html следующим образом:
<body>
你好,江南一点雨!
<form action="/login" method="post">
<table>
<tr>
<td>用户名:</td>
<td><input name="username"></td>
</tr>
<tr>
<td>密码:</td>
<td><input name="password"></td>
</tr>
<tr>
<td><input type="submit" value="登录"></td>
</tr>
</table>
</form>
<h1 th:text="${msg}"></h1>
</body>
Об этой простой функции входа в систему говорить особо нечего.
Посмотрим на интерфейс входа:
@PostMapping("/login")
public String login(String username, String password,Model model) {
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("username", username);
map.add("password", password);
map.add("client_secret", "123");
map.add("client_id", "javaboy");
map.add("grant_type", "password");
Map<String,String> resp = restTemplate.postForObject("http://localhost:8080/oauth/token", map, Map.class);
String access_token = resp.get("access_token");
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Bearer " + access_token);
HttpEntity<Object> httpEntity = new HttpEntity<>(headers);
ResponseEntity<String> entity = restTemplate.exchange("http://localhost:8081/admin/hello", HttpMethod.GET, httpEntity, String.class);
model.addAttribute("msg", entity.getBody());
return "index";
}
В интерфейсе входа, после получения имени пользователя и пароля, мы отправляем POST-запрос через RestTemplate.Обратите внимание, что в почтовом запросе значение параметра grant_type является паролем.Через этот запрос мы можем получить access_token, возвращаемый auth-server в следующем формате:
{access_token=02e3a1e1-925f-4d2c-baac-42d76703cae4, token_type=bearer, refresh_token=836d4b75-fe53-4e41-9df1-2aad6dd80a5d, expires_in=7199, scope=all}
Видно, что возвращаемые данные токена аналогичны предыдущим и здесь повторяться не будут.
После того, как мы извлекли access_token, мы затем запрашиваем сервер ресурсов и помещаем полученные данные в модель.
ОК, после завершения настройки запустите клиентское приложение и получите доступhttp://localhost:8082/index.htmlстраницу для тестирования. После завершения авторизации на главной странице проекта мы можем увидеть следующий контент:
Полный код можно скачать в конце статьи.
3. Режим клиента
Клиентский режим подходит для приложений без интерфейсных страниц, поэтому я буду использовать модульный тест, чтобы продемонстрировать его всем.
Обратите внимание, что следующий код основан на режиме кода авторизации из предыдущей статьи.
Сначала измените auth-server для поддержки режима клиента:
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("javaboy")
.secret(new BCryptPasswordEncoder().encode("123"))
.resourceIds("res1")
.authorizedGrantTypes("client_credentials","refresh_token")
.scopes("all")
.redirectUris("http://localhost:8082/index.html");
}
Все остальное здесь без изменений, в основном добавление режима client_credentials в authorGrantTypes.
После завершения настройки перезапустите сервер авторизации.
Далее в клиентском приложении через модульное тестирование напишем тестовый код:
@Autowired
RestTemplate restTemplate;
@Test
void contextLoads() {
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("client_id", "javaboy");
map.add("client_secret", "123");
map.add("grant_type", "client_credentials");
Map<String,String> resp = restTemplate.postForObject("http://localhost:8080/oauth/token", map, Map.class);
String access_token = resp.get("access_token");
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Bearer " + access_token);
HttpEntity<Object> httpEntity = new HttpEntity<>(headers);
ResponseEntity<String> entity = restTemplate.exchange("http://localhost:8081/hello", HttpMethod.GET, httpEntity, String.class);
System.out.println(entity.getBody());
}
Этот код аналогичен предыдущему, за исключением того, что параметры запроса другие, значение параметра grant_type равно client_credentials. Все остальное то же самое, поэтому я не буду вдаваться в подробности.
Этот модульный тест после завершения выполнения печатает приветствие, и я больше не делаю скриншоты.
Полный код можно скачать в конце статьи.
4. Обновить токен
Затем Сонг Гэ хочет поговорить об общих функциях четырех режимов авторизации.
Взяв в качестве примера режим кода авторизации, когда мы запускаем сервер авторизации, в IntelliJ IDEA мы видим интерфейс, открытый проектом:
Так для чего эти интерфейсы? Мы понимаем это через следующую таблицу:
конечная точка | имея в виду |
---|---|
/oauth/authorize | Это конечная точка авторизации |
/oauth/token | Это конечная точка, используемая для получения токена. |
/oauth/confirm_access | Конечная точка, в которой пользователь подтверждает отправку авторизации (то есть адрес отправки, по которому сервер авторизации спрашивает пользователя, следует ли авторизовать эту страницу) |
/oauth/error | Конечная точка ошибки авторизации |
/oauth/check_token | Конечная точка для проверки access_token |
/oauth/token_key | конечная точка, предоставляющая открытый ключ |
С одного взгляда. Большинство из этих конечных точек использовались нами, а те, которые не использовались, будут использоваться в будущем, и мы подробно объясним их нашим друзьям в то время.
В дополнение к выдаче токенов конечная точка /oauth/token также может использоваться для обновления токенов.Когда мы получаем токены, в дополнение к access_token также есть refresh_token, который используется для обновления токенов.
Я использую postman для простого запроса токена обновления:
Обратите внимание, что при обновлении необходимо использовать параметр refresh_token.После завершения обновления старый access_token станет недействительным.
4. Другое
С помощью трех вышеприведенных случаев в сочетании с предыдущей статьей Сонг Гэ продемонстрировал основное использование четырех режимов авторизации OAuth2 с помощью четырех полных кодов.
Эти четыре полных кейса можно скачать прямо с github:
Хорошо, давайте сначала поговорим так много, если у вас есть что-то, что вы можете получить, вы должны не забыть щелкнуть и подбодрить Сон Гэ~
Адрес дела:GitHub.com/Len VE/OAuth…
Обратите внимание на публичный аккаунт WeChatНебольшой дождь в Цзяннане,Отвечать666Скачать бесплатно Song Ge KnockingСерия учебных пособий по Spring Boot на стр. 274~