SpringBoot基於JustAuth實現第三方授權登錄


1. 簡介

  隨着科技時代日漸繁榮,越來越多的應用融入我們的生活。不同的應用系統不同的用戶密碼,造成了極差的用戶體驗。要是能使用常見的應用賬號實現全應用的認證登錄,將會更加促進應用產品的推廣,為生活增加無限樂趣。
  本文基於JustAuth實現第三方授權登錄,選擇JustAuth原因如下:

  • 支持Github、Gitee、微博、釘釘、百度、Coding、騰訊雲開發者平台、OSChina、支付寶、QQ、微信、淘寶、Google、Facebook、抖音、領英、小米、微軟、今日頭條、Teambition、StackOverflow、Pinterest、人人、華為、企業微信、酷家樂、Gitlab、美團、餓了么和推特等第三方平台的授權登錄;
  • 無需去第三方平台找尋繁雜而龐大的SDK文檔,JustAuth提供了及其簡單的接入方式;
  • 支持自定義OAuth平台;
  • 支持多種方式的State緩存;
  • 支持自定義Http實現;
  • 自定義 Scope,支持更完善的授權體系;
  • 與SpringBoot完美集成,也可整合Spring Security等安全框架;
  • 官網文檔詳細、完善,按照文檔即可完成需求落地。
    官網:https://justauth.wiki/#/

2. 初始化數據庫

  創建數據庫justauth,並初始化表結構:

DROP TABLE IF EXISTS `justauth`.`t_ja_user`;
CREATE TABLE  `justauth`.`t_ja_user` (
  `uuid` varchar(64) NOT NULL COMMENT '用戶第三方系統的唯一id',
  `username` varchar(100) DEFAULT NULL COMMENT '用戶名',
  `nickname` varchar(100) DEFAULT NULL COMMENT '用戶昵稱',
  `avatar` varchar(255) DEFAULT NULL COMMENT '用戶頭像',
  `blog` varchar(255) DEFAULT NULL COMMENT '用戶網址',
  `company` varchar(50) DEFAULT NULL COMMENT '所在公司',
  `location` varchar(255) DEFAULT NULL COMMENT '位置',
  `email` varchar(50) DEFAULT NULL COMMENT '用戶郵箱',
  `gender` varchar(10) DEFAULT NULL COMMENT '性別',
  `remark` varchar(500) DEFAULT NULL COMMENT '用戶備注(各平台中的用戶個人介紹)',
  `source` varchar(20) DEFAULT NULL COMMENT '用戶來源',
  PRIMARY KEY (`uuid`)
);

3. 示例代碼

  使用SpringBoot插件justauth-spring-boot-starter搭建工程。

  • 創建項目
  • 修改pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.c3stones</groupId>
	<artifactId>spring-boot-justauth-demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>spring-boot-justauth-demo</name>
	<description>Spring Boot JustAuth Demo</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.8.RELEASE</version>
		<relativePath />
	</parent>

	<dependencies>
		<dependency>
			<groupId>com.xkcoding.justauth</groupId>
			<artifactId>justauth-spring-boot-starter</artifactId>
			<version>1.3.4.beta</version>
		</dependency>
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-pool2</artifactId>
		</dependency>
		<dependency>
			<groupId>com.baomidou</groupId>
			<artifactId>mybatis-plus-boot-starter</artifactId>
			<version>3.3.1</version>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>cn.hutool</groupId>
			<artifactId>hutool-all</artifactId>
			<version>5.4.1</version>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-redis</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-configuration-processor</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

	<repositories>
		<!--阿里雲私服 -->
		<repository>
			<id>aliyun</id>
			<name>aliyun</name>
			<url>http://maven.aliyun.com/nexus/content/groups/public</url>
		</repository>
		<!--中央倉庫 -->
		<repository>
			<id>oss snapshot</id>
			<name>oss snapshot</name>
			<url>http://oss.sonatype.org/content/repositories/snapshots</url>
			<releases>
				<enabled>true</enabled>
			</releases>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
		</repository>
	</repositories>

</project>
  • 創建響應實體
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

/**
 * 響應實體
 * 
 * @author CL
 *
 */
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class Response {

	/**
	 * 響應碼
	 */
	private int code;

	/**
	 * 響應消息體
	 */
	private String msg;

	/**
	 * 失敗響應
	 * 
	 * @param msg 響應消息體
	 * @return
	 */
	public static Response error(String msg) {
		return new Response(500, msg);
	}

	/**
	 * 成功響應
	 * 
	 * @param msg 響應消息體
	 * @return
	 */
	public static Response success(String msg) {
		return new Response(200, msg);
	}
	
}
  • 創建Redis配置類
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.cache.Cache;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * Redis配置類
 * 
 * @author CL
 *
 */
@Slf4j
@EnableCaching
@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisConfig extends CachingConfigurerSupport {

	/**
	 * 注入RedisTemplate
	 * 
	 * @param redisConnectionFactory Redis連接工廠
	 * @return
	 */
	@Bean(name = "redisTemplate")
	@ConditionalOnMissingBean(name = "redisTemplate")
	public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
		RedisTemplate<Object, Object> template = new RedisTemplate<>();
		template.setValueSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));
		template.setHashValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));
		template.setKeySerializer(new StringRedisSerializer());
		template.setHashKeySerializer(new StringRedisSerializer());
		template.setConnectionFactory(redisConnectionFactory);
		return template;
	}

	/**
	 * 緩存錯誤處理
	 */
	@Bean
	@Override
	public CacheErrorHandler errorHandler() {
		log.info("初始化 -> [{}]", "Redis CacheErrorHandler");
		return new CacheErrorHandler() {
			@Override
			public void handleCacheGetError(RuntimeException e, Cache cache, Object key) {
				log.error("Redis occur handleCacheGetError:key -> [{}]", key, e);
			}

			@Override
			public void handleCachePutError(RuntimeException e, Cache cache, Object key, Object value) {
				log.error("Redis occur handleCachePutError:key -> [{}];value -> [{}]", key, value, e);
			}

			@Override
			public void handleCacheEvictError(RuntimeException e, Cache cache, Object key) {
				log.error("Redis occur handleCacheEvictError:key -> [{}]", key, e);
			}

			@Override
			public void handleCacheClearError(RuntimeException e, Cache cache) {
				log.error("Redis occur handleCacheClearError:", e);
			}
		};
	}

	/**
	 * 注入Redis緩存配置類
	 * 
	 * @return
	 */
	@Bean(name = { "redisCacheConfiguration" })
	public RedisCacheConfiguration redisCacheConfiguration() {
		RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig();
		configuration = configuration
				.serializeKeysWith(
						RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
				.serializeValuesWith(RedisSerializationContext.SerializationPair
						.fromSerializer(new Jackson2JsonRedisSerializer<>(Object.class)));
		return configuration;
	}

}
  • 創建Token緩存到Redis工具類
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;

import com.alibaba.fastjson.JSONObject;

import me.zhyd.oauth.model.AuthToken;

/**
 * 授權Token緩存Redis
 * 
 * @author CL
 *
 */
@Configuration
public class JustAuthTokenCache {

	@SuppressWarnings("rawtypes")
	@Autowired
	private RedisTemplate redisTemplate;

	private BoundHashOperations<String, String, AuthToken> valueOperations;

	@SuppressWarnings("unchecked")
	@PostConstruct
	public void init() {
		valueOperations = redisTemplate.boundHashOps("JUSTAUTH::TOKEN");
	}

	/**
	 * 保存Token
	 * 
	 * @param uuid     用戶uuid
	 * @param authUser 授權用戶
	 * @return
	 */
	public AuthToken saveorUpdate(String uuid, AuthToken authToken) {
		valueOperations.put(uuid, authToken);
		return authToken;
	}

	/**
	 * 根據用戶uuid查詢Token
	 * 
	 * @param uuid 用戶uuid
	 * @return
	 */
	public AuthToken getByUuid(String uuid) {
		Object token = valueOperations.get(uuid);
		if (null == token) {
			return null;
		}
		return JSONObject.parseObject(JSONObject.toJSONString(token), AuthToken.class);
	}

	/**
	 * 查詢所有Token
	 * 
	 * @return
	 */
	public List<AuthToken> listAll() {
		return new LinkedList<>(Objects.requireNonNull(valueOperations.values()));
	}

	/**
	 * 根據用戶uuid移除Token
	 * 
	 * @param uuid 用戶uuid
	 * @return
	 */
	public void remove(String uuid) {
		valueOperations.delete(uuid);
	}

}
  • 創建實體類
import java.io.Serializable;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;

import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import me.zhyd.oauth.model.AuthToken;
import me.zhyd.oauth.model.AuthUser;

/**
 * 授權用戶信息
 * 
 * @author CL
 *
 */
@NoArgsConstructor
@AllArgsConstructor
@TableName(value = "t_ja_user")
public class JustAuthUser extends AuthUser implements Serializable {

	private static final long serialVersionUID = 1L;

	/**
	 * 用戶第三方系統的唯一id。在調用方集成該組件時,可以用uuid + source唯一確定一個用戶
	 */
	@TableId(type = IdType.INPUT)
	private String uuid;

	/**
	 * 用戶授權的token信息
	 */
	@TableField(exist = false)
	private AuthToken token;

	/**
	 * 第三方平台返回的原始用戶信息
	 */
	@TableField(exist = false)
	private JSONObject rawUserInfo;

	/**
	 * 自定義構造函數
	 * 
	 * @param authUser 授權成功后的用戶信息,根據授權平台的不同,獲取的數據完整性也不同
	 */
	public JustAuthUser(AuthUser authUser) {
		super(authUser.getUuid(), authUser.getUsername(), authUser.getNickname(), authUser.getAvatar(),
				authUser.getBlog(), authUser.getCompany(), authUser.getLocation(), authUser.getEmail(),
				authUser.getRemark(), authUser.getGender(), authUser.getSource(), authUser.getToken(),
				authUser.getRawUserInfo());
	}

}
  • 創建Mapper
import org.apache.ibatis.annotations.Mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.c3stones.entity.JustAuthUser;

/**
 * 授權用戶Mapper
 * 
 * @author CL
 *
 */
@Mapper
public interface JustAuthUserMapper extends BaseMapper<JustAuthUser> {

}
  • 創建Service
import com.baomidou.mybatisplus.extension.service.IService;
import com.c3stones.entity.JustAuthUser;

/**
 * 授權用戶Service
 * 
 * @author CL
 *
 */
public interface JustAuthUserService extends IService<JustAuthUser> {

	/**
	 * 保存或更新授權用戶
	 * 
	 * @param justAuthUser 授權用戶
	 * @return
	 */
	boolean saveOrUpdate(JustAuthUser justAuthUser);

	/**
	 * 根據用戶uuid查詢信息
	 * 
	 * @param uuid 用戶uuid
	 * @return
	 */
	JustAuthUser getByUuid(String uuid);

	/**
	 * 根據用戶uuid移除信息
	 * 
	 * @param uuid 用戶uuid
	 * @return
	 */
	boolean removeByUuid(String uuid);

}
  • 創建Service實現類
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.c3stones.cache.JustAuthTokenCache;
import com.c3stones.entity.JustAuthUser;
import com.c3stones.mapper.JustAuthUserMapper;
import com.c3stones.service.JustAuthUserService;

/**
 * 授權用戶Service實現
 * 
 * @author CL
 *
 */
@Service
public class JustAuthUserServiceImpl extends ServiceImpl<JustAuthUserMapper, JustAuthUser>
		implements JustAuthUserService {

	@Autowired
	private JustAuthTokenCache justAuthTokenCache;

	/**
	 * 保存或更新授權用戶
	 * 
	 * @param justAuthUser 授權用戶
	 * @return
	 */
	@Override
	public boolean saveOrUpdate(JustAuthUser justAuthUser) {
		justAuthTokenCache.saveorUpdate(justAuthUser.getUuid(), justAuthUser.getToken());
		return super.saveOrUpdate(justAuthUser);
	}

	/**
	 * 根據用戶uuid查詢信息
	 * 
	 * @param uuid 用戶uuid
	 * @return
	 */
	@Override
	public JustAuthUser getByUuid(String uuid) {
		JustAuthUser justAuthUser = super.getById(uuid);
		if (justAuthUser != null) {
			justAuthUser.setToken(justAuthTokenCache.getByUuid(uuid));
		}
		return justAuthUser;
	}

	/**
	 * 根據用戶uuid移除信息
	 * 
	 * @param uuid 用戶uuid
	 * @return
	 */
	@Override
	public boolean removeByUuid(String uuid) {
		justAuthTokenCache.remove(uuid);
		return super.removeById(uuid);
	}

}
  • 創建授權Controller
import java.io.IOException;

import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSON;
import com.c3stones.common.Response;
import com.c3stones.entity.JustAuthUser;
import com.c3stones.service.JustAuthUserService;
import com.xkcoding.justauth.AuthRequestFactory;

import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.exception.AuthException;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthToken;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.utils.AuthStateUtils;

/**
 * 授權Controller
 * 
 * @author CL
 *
 */
@Slf4j
@RestController
@RequestMapping("/oauth")
public class AuthController {

	@Autowired
	private AuthRequestFactory factory;

	@Autowired
	private JustAuthUserService justAuthUserService;

	/**
	 * 登錄
	 * 
	 * @param type     第三方系統類型,例如:gitee/baidu
	 * @param response
	 * @throws IOException
	 */
	@GetMapping("/login/{type}")
	public void login(@PathVariable String type, HttpServletResponse response) throws IOException {
		AuthRequest authRequest = factory.get(type);
		response.sendRedirect(authRequest.authorize(AuthStateUtils.createState()));
	}

	/**
	 * 登錄回調
	 * 
	 * @param type     第三方系統類型,例如:gitee/baidu
	 * @param callback
	 * @return
	 */
	@SuppressWarnings("unchecked")
	@RequestMapping("/{type}/callback")
	public Response login(@PathVariable String type, AuthCallback callback) {
		AuthRequest authRequest = factory.get(type);
		AuthResponse<AuthUser> response = authRequest.login(callback);
		log.info("【response】= {}", JSON.toJSONString(response));

		if (response.ok()) {
			justAuthUserService.saveOrUpdate(new JustAuthUser(response.getData()));
			return Response.success(JSON.toJSONString(response));
		}
		return Response.error(response.getMsg());
	}

	/**
	 * 收回
	 * 
	 * @param type 第三方系統類型,例如:gitee/baidu
	 * @param uuid 用戶uuid
	 * @return
	 */
	@SuppressWarnings("unchecked")
	@RequestMapping("/revoke/{type}/{uuid}")
	public Response revoke(@PathVariable String type, @PathVariable String uuid) {
		AuthRequest authRequest = factory.get(type);

		JustAuthUser justAuthUser = justAuthUserService.getByUuid(uuid);
		if (null == justAuthUser) {
			return Response.error("用戶不存在");
		}

		AuthResponse<AuthToken> response = null;
		try {
			response = authRequest.revoke(justAuthUser.getToken());
			if (response.ok()) {
				justAuthUserService.removeByUuid(justAuthUser.getUuid());
				return Response.success("用戶 [" + justAuthUser.getUsername() + "] 的 授權狀態 已收回!");
			}
			return Response.error("用戶 [" + justAuthUser.getUsername() + "] 的 授權狀態 收回失敗!" + response.getMsg());
		} catch (AuthException e) {
			return Response.error(e.getErrorMsg());
		}
	}

	/**
	 * 刷新
	 * 
	 * @param type 第三方系統類型,例如:gitee/baidu
	 * @param uuid 用戶uuid
	 * @return
	 */
	@SuppressWarnings("unchecked")
	@RequestMapping("/refresh/{type}/{uuid}")
	@ResponseBody
	public Response refresh(@PathVariable String type, @PathVariable String uuid) {
		AuthRequest authRequest = factory.get(type);

		JustAuthUser justAuthUser = justAuthUserService.getByUuid(uuid);
		if (null == justAuthUser) {
			return Response.error("用戶不存在");
		}

		AuthResponse<AuthToken> response = null;
		try {
			response = authRequest.refresh(justAuthUser.getToken());
			if (response.ok()) {
				justAuthUser.setToken(response.getData());
				justAuthUserService.saveOrUpdate(justAuthUser);
				return Response.success("用戶 [" + justAuthUser.getUsername() + "] 的 access token 已刷新!新的 accessToken: "
						+ response.getData().getAccessToken());
			}
			return Response.error("用戶 [" + justAuthUser.getUsername() + "] 的 access token 刷新失敗!" + response.getMsg());
		} catch (AuthException e) {
			return Response.error(e.getErrorMsg());
		}
	}

}
  • 創建啟動類
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * 啟動類
 * 
 * @author CL
 *
 */
@SpringBootApplication
public class JustAuthApplication {

	public static void main(String[] args) {
		SpringApplication.run(JustAuthApplication.class, args);
	}

}
  • 創建配置文件
      在resources目錄下創建application.yml,其中client-idclient-secret待在對應的開放平台創建應用后回填。
server:
  port: 8443
  
spring:
  datasource:
      driverClassName: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://127.0.0.1:3306/justauth?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull
      username: root
      password: 123456
  redis:
    host: 127.0.0.1
    port: 6379
    password: 123456
    # 連接超時時間(記得添加單位,Duration)
    timeout: 2000ms
    # Redis默認情況下有16個分片,這里配置具體使用的分片
    database: 0
    lettuce:
      pool:
        # 連接池最大連接數(使用負值表示沒有限制) 默認 8
        maxActive: 8
        # 連接池中的最大空閑連接 默認 8
        maxIdle: 8

# Mybatis-plus配置
mybatis-plus:
   mapper-locations: classpath:mapper/*.xml
   global-config:
      db-config:
         id-type: AUTO
   configuration:
      # 打印sql
      log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

# 日志配置          
logging:
  level:
    com.xkcoding: debug
    
# 第三方系統認證
justauth:
  enabled: true
  type:
    BAIDU:
      client-id: xxxxxx
      client-secret: xxxxxx
      redirect-uri: http://127.0.0.1:8443/oauth/baidu/callback
    GITEE:
      client-id: xxx
      client-secret: xxx
      redirect-uri: http://127.0.0.1:8443/oauth/gitee/callback
  cache:
    # 緩存類型(default-使用JustAuth內置的緩存、redis-使用Redis緩存、custom-自定義緩存)
    type: redis
    # 緩存前綴,目前只對redis緩存生效,默認 JUSTAUTH::STATE::
    prefix: 'JUATAUTH::STATE::'
    # 超時時長,目前只對redis緩存生效,默認3分鍾
    timeout: 3m

4. 創建應用

  • 百度創建應用
  1. 注冊百度開發者賬號。
    1.1 注冊開發者賬號:百度Passport
  2. 創建第三方授權應用
    2.1 配置應用:開發者服務管理
    2.2 創建工程

    2.3 安全設置

      將配置文件中justauth.type.BAIDU.redirect-uri的值http://127.0.0.1:8443/oauth/baidu/callback復制到授權回調頁文本框中。
    2.4 信息回填
      將API KeySecret Key復制到配置文件中的justauth.type.BAIDU.client-idjustauth.type.BAIDU.client-secret屬性。
    其他第三方平台創建請瀏覽:集成第三方

5. 測試

  • 登錄
      瀏覽器訪問地址:http://127.0.0.1:8443/oauth/login/baidu,即可獲取到對應信息。
      請觀察數據庫及Redis中數據變化。
  • 刷新Token
      瀏覽器訪問地址:http://127.0.0.1:8443/oauth/refresh/baidu/[uuid],其中uuid為數據庫表中的uuid。
      目前插件中已實現的可刷新的第三方應用有限,請查看AuthRequest.refresh方法的實現類。
      請觀察Redis中數據變化。
  • 移除Token
      瀏覽器訪問地址:http://127.0.0.1:8443/oauth/revoke/baidu/[uuid],其中uuid為數據庫表中的uuid。
      目前插件中已實現的可刷新的第三方應用有限,請查看AuthRequest.revoke方法的實現類。
      請觀察數據庫及Redis中數據變化。

6. 項目地址

  spring-boot-justauth-demo


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM