springboot JWT 搭建授权服务器

这篇具有很好参考价值的文章主要介绍了springboot JWT 搭建授权服务器。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

0 基本介绍

0.1 课程视频

0.2 架构逻辑图

0.2.1 登录JWT与授权服务器交互

0.2.2 登录成功后JWT与gateway-server交互 路由限制

1 JWT私钥公钥

1.1 安装git ->win系统右键 -> git bash here

1.2 生成私钥jks文件

1.3 用私钥jks文件解析出公钥

1.4 保存 BEGIN PUBLIC KEY到txt文件

2 搭建授权服务器

 2.1 加依赖

2.2 yml配置文件

2.3 AuthorizationServerConfig 

2.3.1 添加第三方的客户端

2.3.2 配置验证管理器

2.3.2.1 jwtTokenStore

2.3.2.2 私钥jks 放入resources文件夹

2.3.2.3 JwtAccessTokenConverter ->用私钥jks

2.3.2.4 转化成json格式

2.3.2.3 完整代码

2.4 WebSecurityConfig

2.4.1 AuthenticationManager 授权管理器 Bean

2.4.2 UserDetailsService 用户Bean

2.4.3 PasswordEncoder 密码加密器Bean

2.4.4 安全 跨域

2.4.5 WebSecurityConfig完整代码

3 postman 测试

3.1 测试获取token

3.2 解析token

4 网关gateway-server服务器 验证token是否存在

4.1 加依赖

4.2 yml 配置文件

4.3 过滤器 filter

4.3.1 判断该接口是否需要token

4.3.2 从请求头里读取token 

4.3.3 如果没有token 给用户响应错误

4.3.4 过滤器拦截到用户的请求后->判断redis中是否存在

4.3.5 完整代码

5 postman 测试


0 基本介绍

0.1 课程视频

https://www.bilibili.com/video/BV173411P7M2?p=30&spm_id_from=pageDriver&vd_source=ff8b7f852278821525f11666b36f180a

0.2 架构逻辑图

0.2.1 登录 JWT 授权服务器 Redis

springboot JWT 搭建授权服务器

0.2.2 登录成功后JWT与gateway-server交互 路由限制

springboot JWT 搭建授权服务器

1 JWT私钥公钥

1.1 安装git ->win系统右键 -> git bash here

1.2 生成私钥jks文件

keytool -genkeypair -alias coinexchange -keyalg RSA -keypass coinexchange
-keystore coinexchange.jks -validity 365 -storepass coinexchange

springboot JWT 搭建授权服务器

1.3 用私钥jks文件解析出公钥

keytool -list -rfc --keystore coinexchange.jks | openssl x509 -inform pem
-pubkey

springboot JWT 搭建授权服务器

1.4 保存 BEGIN PUBLIC KEY到txt文件

2 搭建授权服务器

 2.1 加依赖

<!--        服务的发现和注册-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
        </dependency>

        <!--        OAuth2.0-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
        </dependency>
<!--        web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

2.2 yml配置文件

server:
  port: 9999
spring:
  application:
    name: authorization-server
  cloud:
    nacos:
      discovery:
        server-addr: nacos-server:8848

2.3 AuthorizationServerConfig 

2.3.1 添加第三方的客户端

@Autowired
    private PasswordEncoder passwordEncoder; // 密码加密器 
/** 必须配一 ClientDetailsServiceConfigurer
     * 添加第三方的客户端
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        //先配置到内存测试 之后配置到数据库使用
        clients.inMemory() //使用in-memory存储
                .withClient("coin-api") // 第三方客户端的名称 client_id
                .secret(passwordEncoder.encode("coin-secret")) //  第三方客户端的密钥 加密
                .scopes("all") //第三方客户端的授权范围 // 允许的授权范围
                .authorizedGrantTypes("password","refresh_token") // token 过期时间
                .accessTokenValiditySeconds(7 * 24 *3600) // token的有效期
                .refreshTokenValiditySeconds(30 * 24 * 3600)// refresh_token的有效期
                .and()
                .withClient("inside-app")
                .secret(passwordEncoder.encode("inside-secret"))
                .authorizedGrantTypes("client_credentials")
                .scopes("all")
                .accessTokenValiditySeconds(7 * 24 *3600)
        ;
        super.configure(clients);
    }

2.3.2 配置验证管理器

2.3.2.1 jwtTokenStore

 private TokenStore jwtTokenStore() {
        JwtTokenStore jwtTokenStore = new JwtTokenStore(jwtAccessTokenConverter());
        return jwtTokenStore;
    }

2.3.2.2 私钥jks 放入resources文件夹

2.3.2.3 JwtAccessTokenConverter ->用私钥jks

public JwtAccessTokenConverter jwtAccessTokenConverter() {
        JwtAccessTokenConverter tokenConverter = new JwtAccessTokenConverter();

        // 加载我们的私钥 // 要生成一个 放在resources中
        ClassPathResource classPathResource = new ClassPathResource("coinexchange.jks");
        KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(classPathResource, "coinexchange".toCharArray());
        tokenConverter.setKeyPair(keyStoreKeyFactory.getKeyPair("coinexchange", "coinexchange".toCharArray()));
        return tokenConverter;
    }

2.3.2.4 转化成json格式

@Autowired
    private AuthenticationManager authenticationManager;
@Qualifier("userServiceDetailsServiceImpl") // 两种userDetailsService 指定?
    @Autowired
    private UserDetailsService userDetailsService;
/**必须配2 AuthorizationServerEndpointsConfigurer
     * 配置验证管理器,UserdetailService
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager) // 验证管理器
                .userDetailsService(userDetailsService)
                 .tokenStore(jwtTokenStore())// tokenStore 来存储我们的token jwt 存储token
                 .tokenEnhancer(jwtAccessTokenConverter()); // 转成json存储

        super.configure(endpoints);
    }

   

2.3.2.3 完整代码

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
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.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.oauth2.provider.token.store.KeyStoreKeyFactory;
import org.springframework.web.bind.annotation.CrossOrigin;

@EnableAuthorizationServer // 开启授权服务器的功能
@Configuration
@CrossOrigin // @allowOriginsPattens
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { // 点进去有三个方法 就是要配的三个

    @Autowired
    private PasswordEncoder passwordEncoder; // 密码加密器

    @Autowired
    private AuthenticationManager authenticationManager;

//    @Qualifier("userServiceDetailsServiceImpl")
    @Qualifier("userServiceDetailsServiceImpl") // 两种userDetailsService 指定?
    @Autowired
    private UserDetailsService userDetailsService;



    /** 必须配一 ClientDetailsServiceConfigurer
     * 添加第三方的客户端
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        //先配置到内存测试 之后配置到数据库使用
        clients.inMemory() //使用in-memory存储
                .withClient("coin-api") // 第三方客户端的名称 client_id
                .secret(passwordEncoder.encode("coin-secret")) //  第三方客户端的密钥 加密
                .scopes("all") //第三方客户端的授权范围 // 允许的授权范围
                .authorizedGrantTypes("password","refresh_token") // token 过期时间
                .accessTokenValiditySeconds(7 * 24 *3600) // token的有效期
                .refreshTokenValiditySeconds(30 * 24 * 3600)// refresh_token的有效期
                .and()
                .withClient("inside-app")
                .secret(passwordEncoder.encode("inside-secret"))
                .authorizedGrantTypes("client_credentials")
                .scopes("all")
                .accessTokenValiditySeconds(7 * 24 *3600)
        ;
        super.configure(clients);
    }

    /**必须配2 AuthorizationServerEndpointsConfigurer
     * 配置验证管理器,UserdetailService
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager) // 验证管理器
                .userDetailsService(userDetailsService)
                .tokenStore(jwtTokenStore())// tokenStore 来存储我们的token jwt 存储token
                .tokenEnhancer(jwtAccessTokenConverter()); // 转成json存储

        super.configure(endpoints);
    }

    private TokenStore jwtTokenStore() { // TokenStore接口 内存储存适合一台授权服务器,内存不能在多个服务器共享数据 -> redis 共享token
        JwtTokenStore jwtTokenStore = new JwtTokenStore(jwtAccessTokenConverter());
        return jwtTokenStore;
    }

    public JwtAccessTokenConverter jwtAccessTokenConverter() {
        JwtAccessTokenConverter tokenConverter = new JwtAccessTokenConverter();

        // 加载我们的私钥 // 要生成一个 放在resources中
        ClassPathResource classPathResource = new ClassPathResource("coinexchange.jks");
        KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(classPathResource, "coinexchange".toCharArray());
        tokenConverter.setKeyPair(keyStoreKeyFactory.getKeyPair("coinexchange", "coinexchange".toCharArray()));
        return tokenConverter;
    }

}

2.4 WebSecurityConfig

2.4.1 AuthenticationManager 授权管理器 Bean

@Bean // AuthorizationServerConfig 中的授权管理器
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();

2.4.2 UserDetailsService 用户Bean

//    @Bean //  没有搭建amdmin服务器 用假数据测试
//    public UserDetailsService userDetailsService() {
//        InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();
//        User user = new User("admin", "123456", Arrays.asList(new SimpleGrantedAuthority("Role_Admin")));
//        inMemoryUserDetailsManager.createUser(user);
//        return inMemoryUserDetailsManager;
//    }

2.4.3 PasswordEncoder 密码加密器Bean

@Bean // 密码加密器
    public PasswordEncoder passwordEncoder() { //单向校验安全性高,但开销很大,单次密码校验耗时可能高达1秒
        return new BCryptPasswordEncoder();
    }

2.4.4 安全 跨域

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable(); // 跨域
        http.authorizeRequests().anyRequest().authenticated();

2.4.5 WebSecurityConfig完整代码

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

import java.util.Arrays;

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable(); // 跨域
        http.authorizeRequests().anyRequest().authenticated(); // 授权
    }

    @Bean // AuthorizationServerConfig 中的授权管理器
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }


//    @Bean //  没有搭建amdmin服务器 用假数据测试
//    public UserDetailsService userDetailsService() {
//        InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager();
//        User user = new User("admin", "123456", Arrays.asList(new SimpleGrantedAuthority("Role_Admin")));
//        inMemoryUserDetailsManager.createUser(user);
//        return inMemoryUserDetailsManager;
//    }

    /**
     * 密码加密
     *
     * @return
     */
    @Bean // 密码加密器
    public PasswordEncoder passwordEncoder() { //单向校验安全性高,但开销很大,单次密码校验耗时可能高达1秒
        return new BCryptPasswordEncoder();
    }

    //测试密码加密器
    public static void main(String[] args) {
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        String encode = bCryptPasswordEncoder.encode("123456");
        System.out.println(encode);
    }
}

3 postman 测试

3.1 测试获取token

3.2 解析token

https://jwt.io文章来源地址https://www.toymoban.com/news/detail-423017.html

4 网关gateway-server服务器 验证token是否存在

4.1 加依赖

        <!--因为授权服务器判断token 要通过网关 所以redis添加到网关服务器-->
        <dependency> 
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

4.2 yml 配置文件

  redis:
    host: redis-server
    port:
    password: 

4.3 过滤器 filter

4.3.1 判断该接口是否需要token

@Value("${no.require.urls:/admin/login,/user/gt/register}")
    private Set<String> noRequireTokenUris ;
private boolean isRequireToken(ServerWebExchange exchange) {
        String path = exchange.getRequest().getURI().getPath();
        if(noRequireTokenUris.contains(path)){
            return false ; // 不需要token
        }
        if(path.contains("/kline/")){
            return false ;
        }
        return Boolean.TRUE ;
    }

4.3.2 从请求头里读取token 

private String getUserToken(ServerWebExchange exchange) {
        String token = exchange.getRequest().getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
        return token ==null ? null : token.replace("bearer ","") ;
    }

4.3.3 如果没有token 给用户响应错误

private Mono<Void> buildeNoAuthorizationResult(ServerWebExchange exchange) {
        ServerHttpResponse response = exchange.getResponse();
        response.getHeaders().set("Content-Type","application/json"); // 相应类型 json数据
        response.setStatusCode(HttpStatus.UNAUTHORIZED) ; // 相应码 401 
        JSONObject jsonObject = new JSONObject(); // 创建json对象
        jsonObject.put("error","NoAuthorization") ;
        jsonObject.put("errorMsg","Token is Null or Error") ;
        DataBuffer wrap = response.bufferFactory().wrap(jsonObject.toJSONString().getBytes()); // 响应数据
        return response.writeWith(Flux.just(wrap)) ; // 转为流式?Flux.just(wrap)
    }

4.3.4 过滤器拦截到用户的请求后->判断redis中是否存在

@Autowired
    private StringRedisTemplate redisTemplate ;
@Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 1 : 该接口是否需要token 才能访问
        if(!isRequireToken(exchange)){
            return chain.filter(exchange) ;// 不需要token ,直接放行
        }
        // 2: 取出用户的token
        String token = getUserToken(exchange) ;
        // 3 判断用户的token 是否有效
        if(StringUtils.isEmpty(token)){
            return buildeNoAuthorizationResult(exchange) ;
        }
        Boolean hasKey = redisTemplate.hasKey(token);
        if(hasKey!=null && hasKey){
            return chain.filter(exchange) ;// token有效 ,直接放行
        }
        return buildeNoAuthorizationResult(exchange) ;
    }

4.3.5 完整代码

import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.Set;

@Component // 放到容器
public class JwtCheckFilter implements GlobalFilter, Ordered {

    @Autowired
    private StringRedisTemplate redisTemplate ;

    @Value("${no.require.urls:/admin/login,/user/gt/register}")
    private Set<String> noRequireTokenUris ;
    /**
     * 过滤器拦截到用户的请求后做啥
     * @param exchange
     * @param chain
     * @return
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 1 : 该接口是否需要token 才能访问
        if(!isRequireToken(exchange)){
            return chain.filter(exchange) ;// 不需要token ,直接放行
        }
        // 2: 取出用户的token
        String token = getUserToken(exchange) ;
        // 3 判断用户的token 是否有效
        if(StringUtils.isEmpty(token)){
            return buildeNoAuthorizationResult(exchange) ;
        }
        Boolean hasKey = redisTemplate.hasKey(token);
        if(hasKey!=null && hasKey){
            return chain.filter(exchange) ;// token有效 ,直接放行
        }
        return buildeNoAuthorizationResult(exchange) ;
    }

    /**
     * 给用户响应一个没有token的错误
     * @param exchange
     * @return
     */
    private Mono<Void> buildeNoAuthorizationResult(ServerWebExchange exchange) {
        ServerHttpResponse response = exchange.getResponse();
        response.getHeaders().set("Content-Type","application/json"); // 相应json数据
        response.setStatusCode(HttpStatus.UNAUTHORIZED) ;
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("error","NoAuthorization") ;
        jsonObject.put("errorMsg","Token is Null or Error") ;
        DataBuffer wrap = response.bufferFactory().wrap(jsonObject.toJSONString().getBytes());
        return response.writeWith(Flux.just(wrap)) ;
    }

    /**
     * 从 请求头里面获取用户的token
     * @param exchange
     * @return
     */
    private String getUserToken(ServerWebExchange exchange) {
        String token = exchange.getRequest().getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
        return token ==null ? null : token.replace("bearer ","") ; // 去掉bearer
    }

    /**
     * 判断该 接口是否需要token
     * @param exchange
     * @return
     */
    private boolean isRequireToken(ServerWebExchange exchange) {
        String path = exchange.getRequest().getURI().getPath();
        if(noRequireTokenUris.contains(path)){
            return false ; // 不需要token
        }
        if(path.contains("/kline/")){
            return false ;
        }
        return Boolean.TRUE ;
    }


    /**
     * 拦截器的顺序
     * @return
     */
    @Override
    public int getOrder() {
        return 0;
    }
}

5 postman 测试

到了这里,关于springboot JWT 搭建授权服务器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring Boot OAuth2 认证服务器搭建及授权码认证演示

    本篇使用JDK版本是1.8,需要搭建一个OAuth 2.0的认证服务器,用于实现各个系统的单点登录。 这里选择Spring Boot+Spring Security + Spring Authorization Server 实现,具体的版本选择如下: Spirng Boot 2.7.14 , Spring Boot 目前的最新版本是 3.1.2,在官方的介绍中, Spring Boot 3.x 需要JDK 17及以上的

    2024年02月15日
    浏览(50)
  • Linux -- Web服务器 快速搭建静态网站,替换默认网页目录

    先简单写个 页面          我们给网页写了一行内容 作为 静态网页的内容 ( 当然了,写的相当简单,您先理解着看)         可以看到的是,我们将内容 定向到了一个文件里,         这个文件的路径 (  /var/www/html  )熟悉不熟悉???         ===            

    2023年04月19日
    浏览(60)
  • OAuth2.0 实践 Spring Authorization Server 搭建授权服务器 + Resource + Client

    title: OAuth2.0 实践 Spring Authorization Server 搭建授权服务器 + Resource + Client date: 2023-03-27 01:41:26 tags: OAuth2.0 Spring Authorization Server categories: 开发实践 cover: https://cover.png feature: false 目前 Spring 生态中的 OAuth2 授权服务器是 Spring Authorization Server ,原先的 Spring Security OAuth 已经停止更新

    2024年02月08日
    浏览(58)
  • python -m http.server 迅速搭建本地任意目录http.server服务器

    目录 问题描述 解决办法 在工作中,我们经常遇到文件传输这样的事情,小文件传输,一般使用QQ或者微信就能满足,但当传输文件几百MB或者几十G时,这种传输效率就有点捉襟见肘;同时,我们也可以用U盘或者移动硬盘进行拷贝,但偶尔移动硬盘满了或者没有携带时候,就

    2023年04月13日
    浏览(59)
  • 使用node搭建服务器,前端自己写接口,将vue或react打包后生成的dist目录在本地运行

    vue项目打包后生成的dist目录如果直接在本地打开index.html,在浏览器中会报错,无法运行起来。 通常我是放到后端搭建的服务上面去运行,当时前端自己也可以是node,nuxt搭建服务器,写接口等等 如果想在本地运行,我们可以借助node.js+express搭建一个服务器,将打包后的文件部

    2024年02月03日
    浏览(40)
  • Linux系列:开发环境搭建:ubuntu图形界面安装samba服务器、SSH使用、mount -t cifs 挂载windows共享目录方法与问题解决

    samba一种在局域网上共享文件和打印机的一种通信协议,它为局域网内的不同计算机之间提供文件及打印机等资源的共享服务。 通常linux开发环境要和windows平台进行文件交互,使用samba进行文件夹共享,这样会给开发带来很大的便利性,samba安装很简单,下面介绍一下在ubunt

    2024年02月21日
    浏览(73)
  • 如何快速搭建自己的阿里云服务器(宝塔)并且部署springboot+vue项目(全网最全)

    对于新手或者学生党来说,有时候就想租一个云服务器来玩玩或者练练手,duck不必花那么多钱去租个服务器。这些云服务厂商对学生和新手还是相当友好的。下面将教你如何快速搭建自己的阿里云服务器,完成云服务器的部署。 现在阿里云对于新用户来说,还是挺仗义的,

    2024年02月04日
    浏览(84)
  • Spring Security OAuth 2.0 资源服务器— JWT

    目录 一、JWT的最小依赖 二、JWT的最基本配置 1、指定授权服务器 2、初始预期(Startup Expectations) 3、运行时预期(Runtime Expectations) 三、JWT认证是如何工作的 四、直接指定授权服务器 JWK Set Uri 五、提供 audiences 六、覆盖或取代启动自动配置 1、使用jwkSetUri() 2、使用decoder()

    2024年02月05日
    浏览(62)
  • Idea+maven+springboot项目搭建系列--2 整合Rabbitmq完成客户端&服务器端消息收发

    前言:本文通过springBoot -maven 框架,对Rabbitmq 进行整合,完成客户端消息的发送和消费; 1 为什么要使用Rabbitmq: RabbitMQ 是一个可靠的、灵活的、开源的消息中间件,具有以下优点: 异步通信:RabbitMQ 支持异步通信,使得消息发送者和接收者能够异步处理,提高了系统性能和

    2024年02月07日
    浏览(58)
  • 解决远程连接服务器没有远程桌面授权服务器的许可证问题

    解决办法: 1,win键+R打开运行器,使用mstsc -admin命令强制远程 2、输入远程服务器ip、用户名和密码,忽略证书问题的提示框,即可连接进入远程桌面  3,在远程桌面中,打开远程服务器的运行框,使用regedit命令打开注册表  4, 进入计算机HKEY_LOCAL_MACHINESYSTEMCurrentControlS

    2024年02月07日
    浏览(54)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包