【11】Solución de autenticación unificada Spring Cloud OAuth2

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.

Insertar descripción de la imagen aquí

  • 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

  1. Cree un nuevo proyecto m-cloud-oauth-server-9999 basado en m-parent
    Insertar descripción de la imagen aquí
  2. 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>
  1. 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@

  1. clase de inicio
@SpringBootApplication
@EnableDiscoveryClient
@EnableAuthorizationServer //开启认证服务器功能
public class MCloudOuathServer9999 {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(MCloudOuathServer9999.class, args);
    }

}
  1. 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());
    }
}

  1. prueba

Insertar descripción de la imagen aquí

Construir servidor de recursos (servidor de recursos)

  1. m-service-autodeliver-8092Servicios de remodelaciónInsertar descripción de la imagen aquí
  2. Dependencia
    Agregar dependencia del servidor de autenticación OAuth2 al m-service-autodeliver-8092servicio

  3. Nueva configuración en application.yml
oauth2:
  server:
    check-token-url: http://localhost:9999/check_token
  1. 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";
    }
}
  1. Inicie el servicio y verifique
    Insertar descripción de la imagen aquí
  • Se requiere autenticación y no se requiere permiso para acceder a la interfaz.
    Insertar descripción de la imagen aquí
    Insertar descripción de la imagen aquí
  • No es necesario autenticarse y tener permiso para acceder a la interfaz.
    Insertar descripción de la imagen aquí
  • Acceso con token
    1. Obtener token
      Insertar descripción de la imagen aquí
    2. Interfaz de acceso
      Insertar descripción de la imagen aquí

Insertar descripción de la imagen aquí

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...

Supongo que te gusta

Origin blog.csdn.net/u014535922/article/details/130152538
Recomendado
Clasificación