Tabla de contenido
Spring Cloud OAuth2 es la implementación del protocolo OAuth2 del sistema Spring Cloud, que se puede utilizar para la autenticación unificada (verificación de la legitimidad de la identidad) y la autorización (verificación de permisos) para múltiples microservicios. Al enviar un determinado tipo de Grant_type al servicio OAuth2 (servicio unificado de autenticación y autorización) para la autenticación y autorización centralizadas, se obtiene un access_token (token de acceso), y otros microservicios confían en este token.
- Método de autenticación basado en sesión
En un entorno distribuido, la autenticación basada en sesiones causará un problema. Cada servicio de aplicación necesita almacenar
información de identidad del usuario en la sesión. Para solicitudes locales a otro servicio de aplicación a través del equilibrio de carga, debe traer la información de la sesión con usted, de lo contrario
se volverá a autenticar. Podemos utilizar soluciones como compartir sesiones y pegar sesiones.
- Método de autenticación basado en token
Con el método de autenticación basado en token, el servidor no necesita almacenar datos de autenticación, es fácil de mantener y tiene una gran escalabilidad. El cliente puede almacenar el token en cualquier lugar
y puede implementar un mecanismo de autenticación unificado para la web y la aplicación. Sus deficiencias también son obvias: dado que los tokens contienen información autónoma,
la cantidad de datos generalmente es grande y cada solicitud debe transmitirse, por lo que ocupa mucho ancho de banda. Además, la operación de verificación de la firma del token también
supondrá una carga de procesamiento adicional para la CPU.
Introducción a OAuth2
OAuth (Autorización Abierta) es un protocolo/estándar abierto que permite a los usuarios autorizar a aplicaciones de terceros a acceder a su información almacenada en otro proveedor de servicios sin proporcionar nombres de usuario y contraseñas a aplicaciones de terceros ni compartirlos. Todo el contenido de los datos.
- Propietario del recurso: puede entenderse como el propio usuario.
- Cliente: El sitio web o aplicación en la que queremos iniciar sesión, como Lagou.com
- Servidor de autorización: puede entenderse como WeChat o QQ
- Servidor de recursos: puede entenderse como WeChat o QQ
Método de autorización de token de OAuth2
- Código de Autorización
- La contraseña proporciona nombre de usuario + contraseña a cambio de un token.
- implícito
- credenciales del cliente
Construir servidor de autenticación (servidor de autorización)
Servidor de autorización, responsable de emitir tokens
- Cree un nuevo proyecto m-cloud-oauth-server-9999 basado en m-parent
- pom.xml
<!--导⼊Eureka Client依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--导⼊spring cloud oauth2依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.1.11.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.3.4.RELEASE</version>
</dependency>
- application.yml (compila el servidor de autenticación, el archivo de configuración no tiene nada especial)
server:
port: 9999
spring:
application:
name: m-cloud-oauth-server
#注册发现
eureka:
client:
service-url:
defaultZone: http://CloudEurekaServerA:8761/eureka,http://CloudEurekaServerB:8762/eureka
instance:
prefer-ip-address: true
instance-id: ${
spring.cloud.client.ip-address}:${
spring.application.name}:${
server.port}:@project.version@
- clase de inicio
@SpringBootApplication
@EnableDiscoveryClient
@EnableAuthorizationServer //开启认证服务器功能
public class MCloudOuathServer9999 {
public static void main(String[] args) {
SpringApplication.run(MCloudOuathServer9999.class, args);
}
}
- Clase de configuración
- Clase de configuración del servidor de autenticación
package com.w.edu.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
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.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
@Configuration
public class OauthServerConfiger extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
/**
* 认证服务器最终以api接口方式对外提供服务(生成令牌、校验令牌)
*
* @param security
* @throws Exception
*/
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
super.configure(security);
security
//允许客户端表单认证
.allowFormAuthenticationForClients()
//开启端口/oauth/token_key的访问权限
.tokenKeyAccess("permitAll()")
//开启端口/oauth/check_token的访问权限
.checkTokenAccess("permitAll()");
}
/**
* 客户端吧详情配置
*
* @param clients
* @throws Exception
*/
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
super.configure(clients);
//客户端信息存储在什么地方,既可以在内存也可以在数据库里
clients.inMemory()
//添加客户端配置。指定client_id
.withClient("client_w")
//指定客户端密码、安全码
.secret("abcdef")
//指定客户端可访问的资源id 清单
.resourceIds("autodeliver")
//认证类型、客户端令牌颁发模式//认证模式。可以配置多个
.authorizedGrantTypes("password", "refresh_token")
//客户端权限范围,配置all 即可
.scopes("all");
}
/**
* Token 令牌管理相关
*
* @param endpoints
* @throws Exception
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
super.configure(endpoints);
endpoints
//token 存储方式
.tokenStore(tokenStore())
//配置token细节
.tokenServices(authorizationServerTokenServices())
//认证管理器
.authenticationManager(authenticationManager)
.allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST);
}
/**
* Token 存储方式
*
* @return
*/
public TokenStore tokenStore() {
return new InMemoryTokenStore();
}
/**
* 获取Token服务对象,描述token有效期等信息
*
* @return
*/
public AuthorizationServerTokenServices authorizationServerTokenServices() {
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
//开启令牌刷新
defaultTokenServices.setSupportRefreshToken(Boolean.TRUE);
//
defaultTokenServices.setTokenStore(tokenStore());
//设置令牌有效时间(一半2小时)
defaultTokenServices.setAccessTokenValiditySeconds(20);
//设置令牌的有效时间
defaultTokenServices.setRefreshTokenValiditySeconds(259200);
return defaultTokenServices;
}
}
- Clase de configuración de seguridad
package com.w.edu.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import java.util.ArrayList;
/**
* @author Mrwg
* @date 2023/4/13 20:30
* @description
* 处理用户名和密码的校验
*/
@Configuration
public class SecurityConfiger extends WebSecurityConfigurerAdapter {
/**
*注入AuthenticationManager
* @return
* @throws Exception
*/
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public PasswordEncoder passwordEncoder(){
return NoOpPasswordEncoder.getInstance();
}
/**
* 处理用户名密码事宜
* 1 客户传递username 和password 参数到认证服务器
* 2一半存储在数据表中
* 3 根据用户传递的数据,验证当前传递过来用户信息的合法性
* @param auth
* @throws Exception
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 实例化用户对象
UserDetails user = new User("admin","123456",new ArrayList<>());
auth.inMemoryAuthentication()
.withUser(user).passwordEncoder( passwordEncoder());
}
}
- prueba
- token
http://localhost:9999/oauth/token?client_secret=abcdef&grant_type=password&username=admin&password=123456&client_id=client_w- punto final:/oauth/token
- Obtenga los parámetros transportados por el token
client_id : ID del cliente
client_secret : contraseña única del cliente
Grant_type : especifique qué tipo de emisión usar, contraseña
nombre de usuario : nombre de usuario
contraseña : contraseña
- token
http://localhost:9999/oauth/check_token?token=83964ab2-9b37-4c8f-8f4c-1c37a496b902
- Token
http://localhost:9999/oauth/token?grant_type=refresh_token&client_id=client_w&client_secret=abcdef&refresh_token=06c1da97-452f-41ff-a597-89892e43ee49
Construir servidor de recursos (servidor de recursos)
m-service-autodeliver-8092
Servicios de remodelación- Dependencia
Agregar dependencia del servidor de autenticación OAuth2 alm-service-autodeliver-8092
servicio
Nueva configuración en application.yml
oauth2:
server:
check-token-url: http://localhost:9999/check_token
- Agregar controlador de prueba
@RestController
@RequestMapping("/demo")
public class DemoController {
/**
* 使用Feign
*
* @param userId
* @return
*/
@GetMapping("/test")
public String findResumeOpenState() {
return "demo/test";
}
}
@RestController
@RequestMapping("/other")
public class OtherController {
/**
* 使用Feign
*
* @param userId
* @return
*/
@GetMapping("/test")
public String findResumeOpenState() {
return "other/test";
}
}
- Inicie el servicio y verifique
- Se requiere autenticación y no se requiere permiso para acceder a la interfaz.
- No es necesario autenticarse y tener permiso para acceder a la interfaz.
- Acceso con token
- Obtener token
- Interfaz de acceso
- Obtener token
pensar
Pensamiento: cuando iniciamos sesión por primera vez, el servidor de autenticación emite un token y lo almacena en el servidor de autenticación. Más tarde, cuando accedamos al servidor de recursos, llevaremos el token. El servidor de recursos solicitará al servidor de autenticación que verifique el validez del token. Si hay muchos servidores de recursos, entonces el servidor de autenticación estará bajo una gran presión...
Utilice JWT para la transformación. Después de utilizar el mecanismo JWT, el servidor de recursos no necesita acceder al servidor de autenticación...