六一儿童节 全网最全的微服务+Outh2套餐,你确定不来试一试?(入门到精通,附源码)满足你的味蕾需要(二)

2023-11-15

咱们废话不多说,直接开干!!!

目录

一、项目目录

二、Token

三、授权服务器oauth

1.pom

2.application

3.OauthApp启动类

4.DiyUserDetails

5.MyUserDetailService

6.KeyPairController

7.TokenConfig

8.WebSecurityConfig

9.ResourceServerConfig

10.AuthorizationServerConfig

11.授权码模式说明 与 创建数据表

12.测试

(1)获取授权码

(2)获取令牌 

(3)检查令牌

(4)刷新令牌

四、user-service模块与feign模块

五、gateway模块 资源服务器


一、项目目录

feign:远程接口调用

Gateway:资源服务器

Oauth2:授权服务器 

user-service: 普通资源

二、Token

对于Token采用非对称加密,因此到 java 的 bin 目录下打开 cmd,执行以下命令,生成 jwt.jks

keytool -genkey -alias jwt -keyalg RSA -keystore jwt.jks

将其复制到 oauth2 resource 目录下,

三、授权服务器oauth

 

1.pom

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--jwt token -->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-oauth2-jose</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-oauth2-resource-server</artifactId>
        </dependency>
        <!--springboot_redis 缓存 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.white.feign</groupId>
            <artifactId>feign</artifactId>
            <version>1.0</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>com.white</groupId>
            <artifactId>common</artifactId>
            <version>1.0</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>

2.application

server:
  port: 8101
  servlet:
    context-path: /uaa
spring:
  application:
    name: oauth-service
  datasource:
    url: jdbc:mysql://localhost:3306/pay_system?useUnicode=true
    driver-class-name: com.mysql.cj.jdbc.Driver
    username: root
    password: 12345
  main:
    allow‐bean‐definition‐overriding: true
    allow-circular-references: true
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    sentinel:
      transport:
        dashboard: localhost:8080
feign:
  sentinel:
    enabled: true

3.OauthApp启动类

@SpringBootApplication
@EnableFeignClients(basePackages = "com.white.feign.client")
@EnableDiscoveryClient
public class OauthApp
{
    public static void main( String[] args )
    {
        SpringApplication.run(OauthApp.class,args);
    }
}

4.DiyUserDetails

package com.white.oauth2.model;

import com.white.feign.model.User;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class DiyUserDetails extends User implements UserDetails {
    private String username;
    private String password;

    private List<GrantedAuthority> authorities;//授权的
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return authorities;
    }

    @Override
    public String getPassword() {
        return password;
    }

    @Override
    public String getUsername() {
        return username;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }
}

5.MyUserDetailService

这里的UserFeign是在feign模块下定义的

package com.white.oauth2.service;

import com.white.feign.client.UserFeign;
import com.white.feign.model.User;
import com.white.oauth2.model.DiyUserDetails;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 作用:
 * @author: white文
 * @time: 2023/5/23 11:00
 */
@Slf4j
@Service
public class MyUserDetailService implements UserDetailsService {

    @Autowired
    UserFeign userFeign;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        log.info("********开始loadUserByUsername********");
        User user = userFeign.findUser_ByUsername(username);
        if (user==null) throw new UsernameNotFoundException(username);
        List<GrantedAuthority> grantedAuthorities = AuthorityUtils
                .commaSeparatedStringToAuthorityList(user.getIdentity());
        DiyUserDetails details=new DiyUserDetails();
        details.setUsername(username);
        details.setPassword(user.getPassword());
        details.setAuthorities(grantedAuthorities);
        log.info("查询到user为"+user.getUsername()+" 密码"+user.getPassword());
        return details;
    }
}

6.KeyPairController

package com.white.oauth2.controller;

import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.RSAKey;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.security.KeyPair;

import java.security.interfaces.RSAPublicKey;
import java.util.Map;

/**
 * 获取RSA公钥接口
 */
@RestController
public class KeyPairController {

    @Autowired
    private KeyPair keyPair;

    @GetMapping("/rsa/publicKey")
    public Map<String, Object> getKey() {
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        RSAKey key = new RSAKey.Builder(publicKey).build();
        return new JWKSet(key).toJSONObject();
    }

}

7.TokenConfig

package com.white.oauth2.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.rsa.crypto.KeyStoreKeyFactory;

import java.security.KeyPair;

@Configuration
public class TokenConfig {
    public static String KEY="white";

    @Bean
    public TokenStore tokenStore(){
        return new JwtTokenStore(jwtAccessTokenConverter());   //  jwt令牌存储方案
    }

    /**
     * 使用非对称加密算法对token签名
     */
    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setKeyPair(keyPair());
        return converter;
    }

    /**
     * 从classpath下的密钥库中获取密钥对(公钥+私钥)
     */
    @Bean
    public KeyPair keyPair() {
        KeyStoreKeyFactory factory = new KeyStoreKeyFactory(
                new ClassPathResource("jwt.jks"), "white1".toCharArray());
        KeyPair keyPair = factory.getKeyPair(
                "jwt", "white1".toCharArray());
        return keyPair;
    }
}

8.WebSecurityConfig

package com.white.oauth2.config;

import com.white.oauth2.service.MyUserDetailService;
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.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private MyUserDetailService myUserDetailService;

    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }


    @Bean
    //配置密码加密器
    public PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(myUserDetailService).passwordEncoder(passwordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                // 这里要对以下路径放行
                .antMatchers("/oauth/**","/login/**","/logout/**","/rsa/publicKey")
                .permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin().permitAll()
                .and()
                .csrf().disable()
                .httpBasic().disable() // 禁用弹出式认证框
        ;
    }
}

9.ResourceServerConfig

package com.white.oauth2.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    @Autowired
    TokenStore tokenStore;
    public String RESOURCE_ID="USER";

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.resourceId(RESOURCE_ID)
                .tokenStore(tokenStore)
                .stateless(true);
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        //设置需要进行保护的资源路径,默认的情况下是保护资源服务的全部路径
        http
                .authorizeRequests().anyRequest()
                .authenticated()
                .and()
                // 因为查询数据库中的user,用的是feign模块下的UserFeign远程接口调用
                //      对应的就是user路径,所以需要对user路径放行
                .requestMatchers()
                .antMatchers("/user/**")
                .and()
                .formLogin().permitAll()
                //关闭跨域伪造检查
                .and().csrf().disable()
                //把session设置为无状态,意思是使用了token,那么session不再做数据的记录
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }
}

10.AuthorizationServerConfig

package com.white.oauth2.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
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.ClientDetailsService;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
import org.springframework.security.oauth2.provider.code.JdbcAuthorizationCodeServices;
import org.springframework.security.oauth2.provider.token.*;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;

import javax.sql.DataSource;
import java.util.Arrays;
import java.util.List;

/**
 * @AuthorizationServerConfig.java的作用:认证服务器配置
 * @author: white文
 * @time: 2023/5/22 1:02
 */
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    ClientDetailsService clientDetailsService;
    @Autowired
    JwtAccessTokenConverter accessTokenConverter;
    @Autowired
    TokenStore tokenStore;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private AuthorizationCodeServices authorizationCodeServices;

    @Bean
    public AuthorizationServerTokenServices tokenServices() {
        DefaultTokenServices services = new DefaultTokenServices();
        services.setClientDetailsService(clientDetailsService);
        services.setSupportRefreshToken(true);
        services.setTokenStore(tokenStore);
        TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
        tokenEnhancerChain.setTokenEnhancers(Arrays.<TokenEnhancer>asList(accessTokenConverter));
        services.setTokenEnhancer(tokenEnhancerChain);
        services.setAccessTokenValiditySeconds(7200);
        services.setRefreshTokenValiditySeconds(259200);
        return services;
    }


    @Bean
    public ClientDetailsService clientDetailsService(DataSource dataSource) {
        ClientDetailsService clientDetailsService = new JdbcClientDetailsService(dataSource);
        ((JdbcClientDetailsService) clientDetailsService).setPasswordEncoder(passwordEncoder);
        return clientDetailsService;
    }

    //  配置令牌的访问端点
    @Bean
    public AuthorizationCodeServices authorizationCodeServices(DataSource dataSource) {
        //设置授权码模式的授权码如何存取
        return new JdbcAuthorizationCodeServices(dataSource);
    }

    /*
     * 1 用来配置客户端详情服务
     * */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.withClientDetails(clientDetailsService);
    }

    /*
     * 2 配置令牌(token)的访问端点和令牌服务
     * */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints
                .authenticationManager(authenticationManager)
                .authorizationCodeServices(authorizationCodeServices)
                .tokenServices(tokenServices())
                .allowedTokenEndpointRequestMethods(HttpMethod.POST);
    }

    /*
     * 3 配置令牌端点的安全约束
     *   授权服务安全配置:配置哪些路径放行(检查token的路径要放行)
     * */
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.checkTokenAccess("permitAll()")   //对应/oauth/check_token ,路径公开
                .tokenKeyAccess("permitAll()")  // 当使用JwtToken且使用非对称加密时,资源服务用于获取公钥而开放的,这里指这个 endpoint完全公开
                .allowFormAuthenticationForClients(); //允许客户端进行表单身份验证,使用表单认证申请令牌
    }
}

11.授权码模式说明与创建数据表

在这里,授权码模式是基于数据库的,而不是基于内存的,如果基于内存需要写死,这不符合灵活性的要求,所以上面的授权码认证都是基于数据库的,而在上面的application我们已经指定数据库的地址,接下来在指定的数据库中 创建两个数据表 就行,oauth会自动到数据库中找到指定两个数据表名称,并对其进行操作。

CREATE TABLE `oauth_client_details` (
  `client_id` VARCHAR(256) CHARACTER SET utf8 NOT NULL COMMENT '客户端唯一标识ID',
  `resource_ids` VARCHAR(256) CHARACTER SET utf8 DEFAULT NULL COMMENT '客户端所能访问的资源id集合',
  `client_secret` VARCHAR(256) CHARACTER SET utf8 DEFAULT NULL COMMENT '客户端访问密匙',
  `scope` VARCHAR(256) CHARACTER SET utf8 DEFAULT NULL COMMENT '客户端申请的权限范围',
  `authorized_grant_types` VARCHAR(256) CHARACTER SET utf8 DEFAULT NULL COMMENT '客户端授权类型',
  `web_server_redirect_uri` VAR`pay_system`CHAR(256) CHARACTER SET utf8 DEFAULT NULL COMMENT '客户端的重定向URI',
  `authorities` VARCHAR(256) CHARACTER SET utf8 DEFAULT NULL COMMENT '客户端所拥有的权限值',
  `access_token_validity` INT(11) DEFAULT NULL COMMENT '客户端access_token的有效时间(单位:秒)',
  `refresh_token_validity` INT(11) DEFAULT NULL,
  `additional_information` VARCHAR(4096) CHARACTER SET utf8 DEFAULT NULL COMMENT '预留的字段',
  `autoapprove` VARCHAR(256) CHARACTER SET utf8 DEFAULT NULL COMMENT '是否跳过授权(true是,false否)',
  PRIMARY KEY (`client_id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 COMMENT='客户端授权表'

CREATE TABLE `oauth_code` (
`create_time` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP,
`code` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`authentication` BLOB NULL,
INDEX `code_index`(`code`) USING BTREE
) ENGINE = INNODB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = COMPACT;

并且新增一条oauth_client_details表的测试数据:client_secret的明文:111

client_id resource_ids client_secret
123 USER $2a$10$1fAQjm5L.1a52uYklwiIMOKgZpye2ctD6Wv/V1Er8LWh1uyv1wRDG
scope authorized_grant_types web_server_redirect_uri authorities access_token_validity
all authorization_code,refresh_token http://localhost:10000 null 7200
refresh_token_validity additional_information autoapprove
null null true

12.测试

到这里,授权服务器就做好了,我们可以进行测试,注意:在数据表中的测试数据跟请求的链接相关:

(1)获取授权码

  • 输入以下地址(该地址的相关信息跟数据表必须保持一致),自动跳转到login路径下

http://localhost:8101/uaa/oauth/authorize?client_id=123&response_type=code&scop=all&redirect_uri=http://localhost:10000

  • 输入用户名和密码,这里是指你自己的微服务中的用户模块,输入后会通过远程调用UserFeign中指定的服务模块,其下的指定接口。也就是说,在做授权服务器outh2之前,你自己得用user模块,做一个简单的接口即可,查询数据库中指定的用户名
  • 登录成功后就会跳转到指定的重定向路径,并在其尾部有着code参数,即授权码

 

(2)获取令牌 

  •  接下来将授权码代入该地址,来 获取令牌 token

 这里的access_token是我们去请求资源时使用的token,而refresh_token只有在我们需要刷新token的时候才用得到。

(3)检查令牌

  • 可以拿着access_token值去以下地址 检查令牌 ,得到令牌中包含的数据

http://localhost:8101/uaa/oauth/check_token?token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiVVNFUiJdLCJ1c2VyX25hbWUiOiIxMTEiLCJzY29wZSI6WyJhbGwiXSwiZXhwIjoxNjg1NjI5MTU4LCJhdXRob3JpdGllcyI6WyJhZG1pbiJdLCJqdGkiOiJjMlVWSHhPekR6TjFvd3pDMjJRazQwZEktTFEiLCJjbGllbnRfaWQiOiIxMjMifQ.eNpZ9hjAP8MpWIVYzlVeBYhqAbBI9MU5yH8m1kc8EpnCERJtR9cdTbe-1YtqYDFrpgMYpxU2qW8OQDXr74FKj75CCB6Ik-411sGU91Ue7PSa_GKDWujT-0eJavDmDPGRKxS1lhgNdXL1BXGgS38miSa_tNnDoPOx_bydte-Mhi9m9PGBPCyF3taXXV_ARyzBXu183S5Dmv8B_CBNrAk6o7AJPBBBDyNq_puIzR_-HviOHVVsfb1-4qk8wXinS8dZMSJGycay4DKIS7PX8So1IWdXbr4l6SEddFQpnUJ70Af-zNtsFoWUIw_udv4YUZjSlW0IrjqEpXmv2rkGjYMlbQ

 

(4)刷新令牌

  •  当令牌过期时,拿着refresh_token去以下地址 刷新令牌,即可拿到新的令牌token

http://localhost:8101/uaa/oauth/token?grant_type=refresh_token&refresh_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiVVNFUiJdLCJ1c2VyX25hbWUiOiIxMTEiLCJzY29wZSI6WyJhbGwiXSwiYXRpIjoicjhrWWZEcjFDWTFQS0Y2RkZqWTAwMUNia29ZIiwiZXhwIjoxNjg1NzA2NzQyLCJhdXRob3JpdGllcyI6WyJhZG1pbiJdLCJqdGkiOiJhNjNGVkV4N3RHX194UXJDQi05YnBmUWxWakUiLCJjbGllbnRfaWQiOiIxMjMifQ.arUqGU9gpyjZ3g4RsaJDtHHq7jDUgjTfdHwpzdWydM4v7kmvusYb_E9NV7It9GkcRwdpFZBYELaUgM2VIbmon6pMC1TE7LZXb44anSRcUYI8OfiYoSQ8XiJlY8CgNC9wrspWLkw4fXypGUUDUSY6yVS3l_8-kkVi0-EirBFVzNq0rBjlWr1mhGdHZib7JLqPfAdIqC0MDYhXgv4v0ikthkTjz1iDQEDVpJYpx9QXmITnxXCxFtKTSNluzv7M8gJJaJophV1jGF4A6Q8Kt2U_dmxRd07AUSb4dCyik_LOhATPhYYSp9aP7DLnF9bU0u_3_ocp90dxXy3GJwRLQrQ-rQ&client_id=123&client_secret=111

 

 

四、user-service模块与feign模块

由于user-service模块跟feign模块没有涉及到oauth2,也没有导入相关依赖包。

user-service模块作为一个普通的资源模块,feign模块也只是远程调用了user-service模块中的根据用户名查询用户信息给上面的outh2模块而已。

所以,这不是该文章的重点,故不做展示。

五、gateway模块 资源服务器

到此,我们的授权管理器已经结束了,资源服务器在实际开发有两种实现方式:

(1)gateway做网关转发,不做资源服务器,由各个微服务模块自己去做资源服务器;

(2)gateway做网关转发并且做资源服务器。

前者方案使得每一个微服务模块都需要导入oauth2相关依赖,并且做处理,过于繁琐且耦合高。

所以本文章在接下来会采用后者方案进行介绍,也就是文章的重点,并且会介绍到如何解决通过gateway去认证授权,跳转到oauth2认证授权后,跳转不回或重定向不到gatway的bug。

至于我们的gateway模块,会放在下一个文章进行介绍,文章地址将在评论区中展示。

最后,祝大家六一儿童节快乐~~~~~,谁还不是一个宝宝呢!!!

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

六一儿童节 全网最全的微服务+Outh2套餐,你确定不来试一试?(入门到精通,附源码)满足你的味蕾需要(二) 的相关文章

  • WIN10家庭版虚拟机启动蓝屏问题

    关于在WIN10家庭版系统上安装VMware workstation每次启动虚拟机 主机就会出现蓝屏得问题 在刚安装好得时候 启动并没有出现蓝屏 但是使用了几次以后蓝屏几乎每次都会出现 网上查了一下发现好多网友也都遇到得了类似得问题 但是每

随机推荐

  • python绘制qq图_Python中作QQ图(quantilequantile Plot)

    Q Q图主要可以用来回答这些问题 两组数据是否来自同一分布 PS 当然也可以用KS检验 利用python中scipy stats ks 2samp函数可以获得差值KS statistic和P值从而实现判断 两组数据的尺度范围是否一致 两组数
  • HighChar 详解-双Y轴-及各

    网上的例子 数据都是写死的 有点不实用吧 我在这里举一个 展示功能需求的数据 按需从数据库获取并画图展示 本例子结合 angular js 其他前台框架同理 从后台获取数据即可 1 首先要引入Jquery JS 再引入相关highChar
  • 上升子序列用C语言编写,最长上升子序列(C语言 动态规划)

    描述 一个数的序列bi 当b1 lt b2 lt lt bS的时候 我们称这个序列是上升的 对于给定的一个序列 a1 a2 aN 我们可以得到一些上升的子序列 ai1 ai2 aiK 这里1 i1 lt i2 lt lt iK N 比如 对
  • 在html中写的css没效果,css样式不起作用是什么原因?

    在写页面时 有时会发现自己写的css样式无法生效 我们该如何排查css样式无法生效 常见的css样式不起作用的原因有哪些呢 下面我们就来看一下css样式不起作用的原因 排查css样式不起作用的方法步骤 首先 先试一下清除缓存 重启浏览器等手
  • 用 Python 制作一个艺术签名小工具,给自己设计一个优雅的签名

    生活中有很多场景都需要我们签字 签名 如果是一些不重要的场景 我们的签名好坏基本无所谓了 但如果是一些比较重要的场景 如果我们的签名比较差的话 就有可能给别人留下不太好的印象了 俗话说字如其人嘛 本文我们使用 Python 来制作一个艺术签
  • 逐行扫描型Memory LCD显存管理与emWin移植

    因为Memory LCD 的特性 不能设置像素坐标 只能用缓存整体刷新 所以对于Memory LCD来说 emWin移植仅与打点函数有关 这里用Sharp Memory LCD ls013b7dh03 作为实例 LCD的显存 逐行扫描 存放
  • 缓存记录

    1 我们在项目中使用缓存通常都是先检查缓存中是否存在 如果存在直接返回缓存内容 如果不存在就直接查询数据库然后再缓存查询结果返回 这个时候如果我们查询的某一个数据在缓存中一直不存在 就会造成每一次请求都查询DB 这样缓存就失去了意义 在流量
  • 简述锂离子电池的分类及结构

    锂离子电池按所用电解质材料的不同 可分为液态锂离子电池 LIB 和聚合物锂离子电池 PLB 两类 锂电池按工作环境分 高温锂离子电池 低温锂离子电池 常温锂离子电池 按电解质状态分 液态锂离子电池 凝胶锂离子电池固态锂离子电池 按形状分 方
  • uniapp实现横向滚动

  • 【软考】【系统架构设计师】决策论知识点

    1 概念 决策 一词来源于英语Decision Analysis 直译为 做出决定 所谓决策 就是为了实现预定的目标在若干可供选择的方案中 选出一个最佳行动方案的过程 它是一门帮助人们科学地决策的理论 也是管理者识别并解决问题及利用机会的过
  • SQLMAP脚本-sql-labs-Less-26-27a

    testtest sqli labs less 26 and less 26a 观察后端代码 发现空格 or and以及注释符 和 都没了 or and用双写 注释使用 00 空格用 09 0A 0B 0D 20 编写sqlmap脚本命名为
  • PHP运行模式

    PHP运行模式有4钟 1 cgi 通用网关接口 Common Gateway Interface 2 fast cgi 常驻 long live 型的 CGI 3 cli 命令行运行 Command Line Interface 4 web
  • centOS7 安装docker

    centOS7 安装docker centOS7 先更新yum 更新yum sudo yum update 下载必须 yum utils device mapper persistent data lvm2 sudo yum install
  • 本地Docker镜像发布到阿里云的Docker Hub

    1 配置镜像加速器 参考https my oschina net u 182501 blog 1549194 2 命名空间管理 进入https cr console aliyun com namespace index 3 创建镜像仓库 h
  • Java源文件注释

    关于java源程序当中的注释 什么是注释 注释的作用是什么 出现在java的源程序当中 对java源代码的解释说明 注释不会被编译到 class字节码文件当中 一个好的开发习惯应该是多编写注释 这样程序的可读性比较强 java中的注释怎么写
  • C++ 多态 超详细讲解

    文章目录 多态概念引入 1 C 中多态的实现 1 1 多态的构成条件 1 2 虚函数 1 3虚函数的重写 1 4 C 11 override final 1 5 重载 覆盖 重写 重定义 隐藏 2 抽象类 2 1 抽象类的概念 2 2 接口
  • MySQL第四讲 MySql Undo日志 - 对聚簇索引进行CUD操作

    事务需要保证原子性 如果在事务执行过程中出现以下情况 就需要用到undo log 1 事务执行中遇到各种错误 比如服务器本身的错误 操作系统错误甚至是断电导致的错误 2 事务在执行过程手动rollback结束当前事务 每当对一条记录进行改动
  • STM32 定时器中断

    通用定时器工作过程 时钟选择 计数器时钟可以由下列时钟源提供 内部时钟 CK INT 外部时钟模式1 外部输入脚 TIx 外部时钟模式2 外部触发输入 ETR 内部触发输入 ITRx 使用一个定时器作为另一个定时器的预分频器 如可以配置一个
  • 环形队列原理,全网最通俗易懂

    队列是什么 队列是一种很常见的数据结构 满足先进先出的方式 如果我们设定队列的最大长度 那就意味着进队列和出队列的元素的数量实则满足一种动态平衡 如果我们把首次添加入队列的元素作为一个一维坐标的原点 那么随着队列中元素的添加 坐标原点到队尾
  • 六一儿童节 全网最全的微服务+Outh2套餐,你确定不来试一试?(入门到精通,附源码)满足你的味蕾需要(二)

    咱们废话不多说 直接开干 目录 一 项目目录 二 Token 三 授权服务器oauth 1 pom 2 application 3 OauthApp启动类 4 DiyUserDetails 5 MyUserDetailService 6 K