【11】Solução de autenticação unificada Spring Cloud OAuth2

Spring Cloud OAuth2 é a implementação do sistema Spring Cloud do protocolo OAuth2, que pode ser usado para autenticação unificada (verificação de legitimidade de identidade) e autorização (verificação de permissões) para vários microsserviços. Ao enviar um determinado tipo de grant_type ao serviço OAuth2 (serviço de autenticação e autorização unificada) para autenticação e autorização centralizada, um access_token (token de acesso) é obtido, e esse token é confiável para outros microsserviços

  • Método de autenticação baseado em sessão

Em um ambiente distribuído, a autenticação baseada em sessão causará um problema. Cada serviço de aplicativo precisa armazenar
informações de identidade do usuário na sessão. Para locais para outro serviço de aplicativo por meio de balanceamento de carga, ele precisa trazer as informações da sessão com você, caso contrário
ele será autenticado novamente. Podemos usar soluções como compartilhamento de sessão e colagem de sessão

  • Método de autenticação baseado em token

Com o método de autenticação baseado em token, o servidor não precisa armazenar dados de autenticação, é fácil de manter e tem forte escalabilidade. O cliente pode armazenar o token em qualquer lugar
e pode implementar um mecanismo de autenticação unificado para web e aplicativos. Suas deficiências também são óbvias: como os tokens contêm informações independentes,
a quantidade de dados geralmente é grande e cada solicitação precisa ser transmitida, por isso ocupa muita largura de banda. Além disso, a operação de verificação de assinatura de token também
trará carga adicional de processamento para a CPU.

Introdução ao OAuth2

OAuth (Open Authorization) é um protocolo/padrão aberto que permite aos usuários autorizar aplicativos de terceiros a acessar suas informações armazenadas em outro provedor de serviços sem fornecer nomes de usuário e senhas a aplicativos de terceiros ou compartilhá-los Todo o conteúdo dos dados

Insira a descrição da imagem aqui

  • Proprietário do recurso: pode ser entendido como o próprio usuário
  • Cliente: O site ou aplicativo no qual queremos fazer login, como Lagou.com
  • Servidor de Autorização: Pode ser entendido como WeChat ou QQ
  • Servidor de recursos: pode ser entendido como WeChat ou QQ

Método de autorização de token do OAuth2

  • Código de autorização
  • A senha fornece nome de usuário + senha em troca de token.
  • implícito
  • credenciais do cliente

Construir servidor de autenticação (servidor de autorização)

Servidor de Autorização, responsável pela emissão de tokens

  1. Crie um novo projeto m-cloud-oauth-server-9999 baseado em m-parent
    Insira a descrição da imagem aqui
  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 (construir servidor de autenticação, arquivo de configuração não tem nada de 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. Aula de inicialização
@SpringBootApplication
@EnableDiscoveryClient
@EnableAuthorizationServer //开启认证服务器功能
public class MCloudOuathServer9999 {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(MCloudOuathServer9999.class, args);
    }

}
  1. Classe de configuração
  • Classe de configuração do servidor de autenticação
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;
    }
}

  • Classe de configuração de segurança
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. teste

Insira a descrição da imagem aqui

Construir servidor de recursos (servidor de recursos)

  1. m-service-autodeliver-8092Serviços de remodelaçãoInsira a descrição da imagem aqui
  2. Dependência
    Adicionar dependência OAuth2 do servidor de autenticação ao m-service-autodeliver-8092serviço

  3. Nova configuração em application.yml
oauth2:
  server:
    check-token-url: http://localhost:9999/check_token
  1. Adicionar controlador de teste
@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 o serviço e verifique
    Insira a descrição da imagem aqui
  • A autenticação é necessária e nenhuma permissão é necessária para acessar a interface.
    Insira a descrição da imagem aqui
    Insira a descrição da imagem aqui
  • Não há necessidade de autenticação e permissão para acessar a interface
    Insira a descrição da imagem aqui
  • Acesso com token
    1. Obter token
      Insira a descrição da imagem aqui
    2. Interface de acesso
      Insira a descrição da imagem aqui

Insira a descrição da imagem aqui

pensar

Pensando: Quando fazemos login pela primeira vez, o servidor de autenticação emite um token e o armazena no servidor de autenticação. Mais tarde, quando acessarmos o servidor de recursos, carregaremos o token. O servidor de recursos solicitará ao servidor de autenticação para verificar o validade do token. Se houver muitos servidores de recursos, o servidor de autenticação estará sob grande pressão...

Use JWT para transformação. Depois de usar o mecanismo JWT, o servidor de recursos não precisa acessar o servidor de autenticação...

Acho que você gosta

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