@[TOC](режим кода авторизации серии OAuth2.0 (код авторизации) практическое руководство (2))
Блог серии OAuth2.0:
- Основная концепция и рабочий процесс серии OAuth2.0 (1)
- Практическое руководство по режиму кода авторизации серии OAuth2.0 (2)
- Практическое руководство по упрощенному режиму серии OAuth2.0 (3)
- Практическое руководство по режиму пароля серии OAuth2.0 (4)
- Практический курс по клиентскому режиму серии OAuth2.0 (5)
- Учебное пособие по хранению информационных баз данных серии OAuth2.0 (6)
- Учебное пособие по хранилищу данных Redis серии OAuth2.0 (7)
- Практическое руководство по токену JWT серии OAuth2.0 (8)
- Серия OAuth2.0 интегрировала JWT для обеспечения единого входа
1. Введение в режим кода авторизации
1.1 Введение
существуетпредыдущий постМы изучили некоторые основные концепции OAuth2, получили общее представление об OAuth2, а затем изучили режим кода авторизации в режиме авторизации OAuth2.0.
PS: режим авторизации OAUTH2.0 можно разделить на:
- Код авторизации
- Упрощенный режим (неявный)
- Режим пароля (учетные данные пароля владельца ресурса)
- Режим клиента (учетные данные клиента)
Метод кода авторизации означает, что стороннее приложение сначала запрашивает код авторизации, а затем использует этот код для получения токена. Режим кода авторизации — это режим авторизации с наиболее полными функциями, наиболее широко используемым и самым строгим процессом.
1.2 Блок-схема авторизации
Официальные изображения сайта:
- (A): Клиент несет client_id, redirect_uri и передает агента через агента через агента.Если вы уже вошли в систему, верните redirect_uri напрямую, без входа на страницу входа
- (B) сервер авторизации для аутентификации клиента (пользовательский агент, позволяющий пользователям вводить имя пользователя и пароль)
- (C) После того, как авторизация будет пройдена, она будет перенаправлена на redirect_uri и будет содержать код кода авторизации в качестве параметра uri.
- (D) Клиент несет код авторизации для доступа к серверу авторизации
- (E) Убедитесь, что код авторизации передан, и верните acceptToken
В плане настройки интерфейса, если говорить простым языком:
-
Шаг 1: Получите код: например: oauthServer+"/oauth/authorize?client_id="+clientId+"&response_type=code&redirect_uri="+redirectUrl+"&scope=all" Если вы не вошли в систему, вы будете перенаправлены на страницу входа в систему единой аутентификации. Если пользователь залогинился, то после вызова интерфейса он будет перенаправлен на redirect_uri, а в качестве его параметра будет использоваться код авторизации
-
Шаг 2: Получите access_token например: oauthServer+"/oauth/token?code="+code+"&grant_type=authorization_code&client_secret="+clientSecret+"&redirect_uri="+redirectUri+"&client_id="+clientId
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1ODk1MzQ5NzMsInVzZXJfbmFtZSI6Im5pY2t5IiwiYXV0aG9yaXRpZXMiOlsiUk9MRV9hZG1pbiJdLCJqdGkiOiJmMjM0M2Q0NC1hODViLTQyOGYtOWE1ZS1iNTE4NTAwNTM5ODgiLCJjbGllbnRfaWQiOiJvYSIsInNjb3BlIjpbImFsbCJdfQ.LWkN2gC2dBrGTn5uSPzfdW6yRj7jhlX87EE8scY02hI",
"token_type": "bearer",
"expires_in": 59,
"scope": "all",
"user_name": "nicky",
"jti": "f2343d44-a85b-428f-9a5e-b51850053988"
}
- Шаг 3: Доступ к системным ресурсам.В это время единая служба проверки подлинности будет определять, следует ли возвращать информацию, на основе информации об авторизации клиента проверки подлинности.
доступ:http://localhost:8084/api/userinfo?access_token=${accept_token}
2. Пример практики
2.1 Подготовка экспериментальной среды
- IntelliJ IDEA
- Версия Maven3.+ Создайте новый проект SpringBoot Initializer, вы можете назвать author_code
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Cloud Oauth2-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<!-- Spring Cloud Security-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-security</artifactId>
</dependency>
2.2 Роли OAuth2.0
В предыдущем исследовании мы знали, что OAuth 2.0 в основном включает следующие роли.Давайте углубим наше понимание теории с помощью примеров кода.
- Владелец ресурса
- Агент пользователя
- Клиент (Клиент)
- Сервер авторизации
- Сервер ресурсов
Рабочая среда, сервер ресурсов и сервер авторизации, как правило, разделены, но обучение можно объединить.
Определите сервер ресурсов с помощью аннотации @EnableResourceServer; Определите сервер авторизации с помощью аннотации @EnableAuthorizationServer;
2.3 Класс конфигурации OAuth2.0
package com.example.springboot.authorizationcode.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
/**
* <pre>
* OAuth2.0配置类
* </pre>
*
* <pre>
* @author mazq
* 修改记录
* 修改后版本: 修改人: 修改日期: 2020/06/11 11:00 修改内容:
* </pre>
*/
@Configuration
//开启授权服务
@EnableAuthorizationServer
public class OAuth2Config extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
private static final String CLIENT_ID = "cms";
private static final String SECRET_CHAR_SEQUENCE = "{noop}secret";
private static final String SCOPE_READ = "read";
private static final String SCOPE_WRITE = "write";
private static final String TRUST = "trust";
private static final String USER ="user";
private static final String ALL = "all";
private static final int ACCESS_TOKEN_VALIDITY_SECONDS = 2*60;
private static final int FREFRESH_TOKEN_VALIDITY_SECONDS = 2*60;
// 密码模式授权模式
private static final String GRANT_TYPE_PASSWORD = "password";
//授权码模式
private static final String AUTHORIZATION_CODE = "authorization_code";
//refresh token模式
private static final String REFRESH_TOKEN = "refresh_token";
//简化授权模式
private static final String IMPLICIT = "implicit";
//指定哪些资源是需要授权验证的
private static final String RESOURCE_ID = "resource_id";
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
// 使用内存存储
.inMemory()
//标记客户端id
.withClient(CLIENT_ID)
//客户端安全码
.secret(SECRET_CHAR_SEQUENCE)
//为true 直接自动授权成功返回code
.autoApprove(true)
.redirectUris("http://127.0.0.1:8084/cms/login") //重定向uri
//允许授权范围
.scopes(ALL)
//token 时间秒
.accessTokenValiditySeconds(ACCESS_TOKEN_VALIDITY_SECONDS)
//刷新token 时间 秒
.refreshTokenValiditySeconds(FREFRESH_TOKEN_VALIDITY_SECONDS)
//允许授权类型
.authorizedGrantTypes(AUTHORIZATION_CODE );
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
// 使用内存保存生成的token
endpoints.authenticationManager(authenticationManager).tokenStore(memoryTokenStore());
}
/**
* 认证服务器的安全配置
*
* @param security
* @throws Exception
*/
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security
//.realm(RESOURCE_ID)
// 开启/oauth/token_key验证端口认证权限访问
.tokenKeyAccess("isAuthenticated()")
// 开启/oauth/check_token验证端口认证权限访问
.checkTokenAccess("isAuthenticated()")
//允许表单认证
.allowFormAuthenticationForClients();
}
@Bean
public TokenStore memoryTokenStore() {
// 最基本的InMemoryTokenStore生成token
return new InMemoryTokenStore();
}
}
2.4 Класс конфигурации безопасности
Для тестирования можно использовать простой SpringSecurity.
package com.example.springboot.authorizationcode.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
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.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
/**
* <pre>
* SpringSecurity配置类
* </pre>
*
* <pre>
* @author mazq
* 修改记录
* 修改后版本: 修改人: 修改日期: 2020/06/11 11:23 修改内容:
* </pre>
*/
@Configuration
@EnableWebSecurity
@Order(1)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception { //auth.inMemoryAuthentication()
auth.inMemoryAuthentication()
.withUser("nicky")
.password("{noop}123")
.roles("admin");
}
@Override
public void configure(WebSecurity web) throws Exception {
//解决静态资源被拦截的问题
web.ignoring().antMatchers("/asserts/**");
web.ignoring().antMatchers("/favicon.ico");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http // 配置登录页并允许访问
.formLogin().permitAll()
// 配置Basic登录
//.and().httpBasic()
// 配置登出页面
.and().logout().logoutUrl("/logout").logoutSuccessUrl("/")
.and().authorizeRequests().antMatchers("/oauth/**", "/login/**", "/logout/**").permitAll()
// 其余所有请求全部需要鉴权认证
.anyRequest().authenticated()
// 关闭跨域保护;
.and().csrf().disable();
}
}
2.5 Простой функциональный тест
Доступ к ссылке авторизации вы можете получить доступ к нему в браузере и пройти код в параметре Repeate_Type режима авторизации:http://localhost:8888/oauth/authorize?client_id=cms&client_secret=secret&response_type=code
Поскольку входа нет, он вернется на страницу входа SpringSecurity по умолчанию, конкретный кодhttp .formLogin().permitAll();
, если вы хотите войти в систему с всплывающим окном, вы можете настроитьhttp.httpBasic();
, в этой конфигурации нет страницы входа, пользовательскую страницу входа можно настроить следующим образомhttp.formLogin().loginPage("/login").permitAll()
Как показано на рисунке, введите пароль статической учетной записи, настроенный Spring Security: nicky/123.
Вход выполнен успешно, верните redirect_uri и получите код авторизацииhttp://127.0.0.1:8084/cms/login?code=lA4EAJ
Получите код кода авторизации для получения токена
жетон:{
"access_token": "dcb626c2-e514-4a8c-8df1-90fe5b5baabf",
"token_type": "bearer",
"expires_in": 119,
"scope": "all"
}
Обратите внимание на настройку параметров авторизации заголовка запроса, имя пользователя client_id, пароль client_secret
Запрос метода кода может быть инкапсулирован следующим образом, то есть шифрование base64.
HttpHeaders headers = new HttpHeaders();
byte[] key = (clientId+":"+clientSecret).getBytes();
String authKey = new String(Base64.encodeBase64(key));
LOG.info("Authorization:{}","Basic "+authKey);
headers.add("Authorization","Basic "+authKey);
Пример загрузки кода:code download