JustAuth,如你所见,它仅仅是一个第三方授权登录工具类库,它可以让我们脱离繁琐的第三方登录SDK,让登录变得So easy!

github地址:https://github.com/justauth/JustAuth

对于spirng boot+Vue前后端分离的项目实现第三方登录比单纯spring boot相对比较麻烦,所以在此做个记录。

1. 环境准备

1.1. 公网服务器准备

首先准备一台有公网 IP 的服务器,可以选用阿里云或者腾讯云,百度云也行,好像百度云最近有优惠。

1.2. 内网穿透 frp 搭建

frp 安装程序:https://github.com/fatedier/frp/releases

1.2.1. frp 服务端搭建

服务端搭建在上一步准备的公网服务器上,因为服务器是 centos7 x64 的系统,因此,这里下载安装包版本为 linux_amd64 的 frp_0.29.1_linux_amd64.tar.gz 。

用shell远程连接服务器,命令行输入

  1. 下载安装包(下载速度可能会比较慢)

    $ wget https://github.com/fatedier/frp/releases/download/v0.29.1/frp_0.29.1_linux_amd64.tar.gz
  2. 解压安装包
    $ tar -zxvf frp_0.29.1_linux_amd64.tar.gz
  3. 修改配置
    $ cd frp_0.29.1_linux_amd64
    $ vim frps.ini[common]
    bind_port = 7100
    vhost_http_port = 7200
  4. 启动 frp 服务端   注意:/root/frp_0.29.1_linux_amd64为frps安装的绝对路径
    $nohup /root/frp_0.29.1_linux_amd64/frps -c  /root/frp_0.29.1_linux_amd64/frps.ininohup: ignoring input and appending output to ‘nohup.out’
    

运行后frps的运行日志将会在‘nohup.out’文件中输出

1.2.2. frp 客户端搭建

客户端搭建在本地的 Windows 上,因此下载安装包版本为 windows_amd64 的 frp_0.29.1_windows_amd64.zip 。

1.直接下载压缩安装包

https://github.com/fatedier/frp/releases/download/v0.29.1/frp_0.29.1_windows_amd64.zip

2.解压文件到自己的电脑中

3.修改配置文件frpc.ini

[common]
server_addr = 119.29.528.35
server_port = 7000[web]
type = http
local_port = 8080
custom_domains = www.example.cn

server_addr = 你外网的服务器

Iplocal_port = 你本地spring boot运行端口
custom_domains 你外网服务器IP进行dns绑定的域名

4.启动frpc客户端(双击直接运行我好像运行不起来)使用CMD执行以下命令

//切换到解压文件目录
c:> cd frp_0.29.1_windows_amd64
//运行
c:> frpc.exe
2019/11/21 10:20:35 [I] [service.go:249] [01a75fadd6a3998d] login to server success, get run id [01a75fadd6a3998d], server udp port [0]
2019/11/21 10:20:35 [I] [proxy_manager.go:144] [01a75fadd6a3998d] proxy added: [web]
2019/11/21 10:20:35 [I] [control.go:164] [01a75fadd6a3998d] [web] start proxy success

:现在当我们在浏览器输入 http://www.eample.com :7200的时候,网络流量其实会经历以下几个步骤:

  1. 通过之前配的 DNS 域名解析会访问到我们的公网服务器 119.29.528.35 的 7200端口
  2. 再经过 frp 穿透到我们的 windows电脑的 8080 端口
  3. 此时 8080 就是我们的应用程序端口

如果需要去掉7200端口可以自己配置nginx进行代理到本地的 7200 端口,需要的话自己百度

1.3. 第三方平台申请

  1. 前往 https://connect.qq.com/

  2. 申请开发者

  3. 应用管理 -> 添加网站应用,等待审核通过即可

其他平台相类似;

2. 主要代码

思路:用户点击前端Vue第三方按钮,后端/render/{source}接口授权接收请求返回重定向的第三方登录地址,前端Vue接收到后可直接跳转到授权界面或者通过弹窗的方式打开第三方登录界面也行,登录成功后第三方返回回调地址到我们外网的域名,在经过我们的内网映射到本地到/callback/{source}接口,我们获取到token后进行数据库数据存储,并用Token去获取openid和其他信息,我们创建uuid产生Key用redis进行保存用户信息,并把key携带到地址中重定向到首页,首页解析地址是否包含我们携带的key有的话就可以到后台redis中请求到用户的信息了,返回前端后提示登录成功并跳转到用户中心界面。

2.1. pom.xml

<!--第三方授权登录的工具类JustAuth库-->
<dependency><groupId>me.zhyd.oauth</groupId><artifactId>JustAuth</artifactId><version>1.13.1</version>
</dependency>
<!-- Lombok -->
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId>
</dependency>
<!-- Redis -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency><!-- mybatis-plus --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>${mybatis-plus.version}</version></dependency><!-- druid -->
<dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>${druid.version}</version>
</dependency>

2.2 application.yml配置

server:port: 8080servlet:context-path: /oauthspring:redis:host: localhost# 连接超时时间(记得添加单位,Duration)timeout: 10000ms# Redis默认情况下有16个分片,这里配置具体使用的分片# database: 0lettuce:pool:# 连接池最大连接数(使用负值表示没有限制) 默认 8max-active: 8# 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1max-wait: -1ms# 连接池中的最大空闲连接 默认 8max-idle: 8# 连接池中的最小空闲连接 默认 0min-idle: 0cache:# 一般来说是不用配置的,Spring Cache 会根据依赖的包自行装配type: redis
datasource:master:url: jdbc:mysql://127.0.0.1:3306/oauth?characterEncoding=UTF-8&useUnicode=true&useSSL=falseusername: rootpassword: rootdriver-class-name: com.mysql.jdbc.Driver

2.3 创建数据库表oauth并创建表结构

-- ----------------------------
-- Table structure for sys_user_social
-- ----------------------------
DROP TABLE IF EXISTS `sys_user_social`;
CREATE TABLE `sys_user_social` (`userId` varchar(255) NOT NULL COMMENT '用户Id',`providerId` varchar(255) NOT NULL COMMENT '平台类型qq,wechat,weibo等',`providerUserId` varchar(255) NOT NULL COMMENT '社交平台唯一ID',`rank` int(11) NOT NULL DEFAULT '0' COMMENT '等级',`displayName` varchar(255) DEFAULT NULL COMMENT '昵称',`profileUrl` varchar(512) DEFAULT NULL COMMENT '配置文件地址',`imageUrl` varchar(512) DEFAULT NULL COMMENT '头像地址',`accessToken` varchar(512) NOT NULL COMMENT 'token',`secret` varchar(512) DEFAULT NULL COMMENT '秘钥',`refreshToken` varchar(512) DEFAULT NULL COMMENT '刷新token',`expireTime` bigint(20) DEFAULT NULL COMMENT '过期时间',`create_by` varchar(32) DEFAULT NULL COMMENT '创建人',`create_time` datetime DEFAULT NULL COMMENT '创建时间',`update_by` varchar(32) DEFAULT NULL COMMENT '更新人',`update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',PRIMARY KEY (`userId`,`providerId`,`providerUserId`),UNIQUE KEY `UserConnectionRank` (`userId`,`providerId`,`rank`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='社交登录表';

2.4 写控制类

/*** @author 淋汾* @version 1.0* @description 第三方授权登录* @date 2019/11/19 9:28*/
@RestController
@RequestMapping("/oauth")
public class LoginOauthController {@Autowiredprivate RedisUtil redisUtil;@Autowiredprivate ISysUserSocialService userSocialService;@Autowiredprivate ISysDepartService sysDepartService;@Autowiredprivate ISysUserService sysUserService;@Autowiredprivate ISysBaseAPI sysBaseAPI;//第三方登录回调地址private String callBackBaseUrl = "http://www.example.cn:7200/oauth/oauth/callback";//本地授权成功重定向地址private String url = "http://127.0.0.1:8081";/*** 授权请求地址** @param source* @param response* @return* @throws IOException*/@RequestMapping("/render/{source}")public Result<String> renderAuth(@PathVariable("source") String source, HttpServletResponse response) throws IOException {System.out.println("进入render:" + source);AuthRequest authRequest = getAuthRequest(source);String authorizeUrl = authRequest.authorize(AuthStateUtils.createState());System.out.println(authorizeUrl);Result<String> result = new Result<String>();result.setSuccess(true);result.setResult(authorizeUrl);result.setMessage("正在进行跳转");
//        response.sendRedirect(authorizeUrl);return result;}/*** oauth平台中配置的授权回调地址,以本项目为例,在创建github授权应用时的回调地址应为:http://127.0.0.1:8080/oauth/callback/github*/@RequestMapping("/callback/{source}")public Object login(@PathVariable("source") String source, AuthCallback callback, HttpServletResponse response) throws IOException {String uuid = "";Result<JSONObject> result = new Result<JSONObject>();System.out.println("进入callback:" + source + " callback params:" +JSONObject.toJSONString(callback));AuthRequest authRequest = getAuthRequest(source);AuthResponse<AuthUser> authResponse = authRequest.login(callback);System.out.println(JSONObject.toJSONString(authResponse));/*  switch (source) {case "weibo":authResponse.getData().getToken().getOpenId();break;}
*///通过getProviderid和getProviderUserId查询用户if (authResponse == null) {result.error500("授权失败");return result;}SysUserSocial sysUserSocial = userSocialService.lambdaQuery().eq(SysUserSocial::getProviderid, source).eq(SysUserSocial::getProvideruserid, authResponse.getData().getToken().getOpenId()).one();if (sysUserSocial == null) {AuthToken token = authResponse.getData().getToken();sysUserSocial = new SysUserSocial();sysUserSocial.setProviderid(source);sysUserSocial.setProvideruserid(token.getOpenId());sysUserSocial.setAccesstoken(token.getAccessToken());sysUserSocial.setRefreshtoken(token.getRefreshToken());sysUserSocial.setExpiretime(token.getExpireIn());sysUserSocial.setDisplayname(authResponse.getData().getUsername());sysUserSocial.setProfileurl(authResponse.getData().getBlog());sysUserSocial.setImageurl(authResponse.getData().getAvatar());sysUserSocial.setSecret(token.getOauthTokenSecret());//TODO 社交账户未绑定用户数据库,进行绑定uuid = UUID.randomUUID().toString();redisUtil.set(uuid, sysUserSocial, 1000 * 60 * 10);System.out.println("存数据的key"+uuid);result.error500("社交账户未绑定用户");response.sendRedirect(url + "/user/social-bind?key=" + uuid);return result;}//通过用户ID超找用户,并进行登录SysUser user = sysUserService.getById(sysUserSocial.getUserid());if (user == null) {result.error500("未找到用户,请绑定用户");return result;}//用户登录信息userInfo(user, result);sysBaseAPI.addLog("用户名: " + user.getUsername() + ",第三方" + source + "登录成功!", CommonConstant.LOG_TYPE_1, null);uuid = UUID.randomUUID().toString();redisUtil.set(uuid, result.getResult(), 1000 * 60 * 10);response.sendRedirect(url + "/user/login?key=" + uuid);return result;}@PostMapping("/user_info")public Result<JSONObject>  getSocialUserInfo(@RequestBody String key) {Result<JSONObject> result = new Result<JSONObject>();System.out.println("获取数据的key"+key);if (key == null || key.equals("")) {return result.error500("key不能为空");}key = JSON.parseObject(key).getString("key");//从Redis读取数据Object data = redisUtil.get(key);//删除Redis中的数据redisUtil.del(key);if (data == null) {return result.error500("数据请求失败");}result.setResult((JSONObject) data);result.success("登录成功");return result;}/*** 社交登录绑定* @param user 登录信息* @return*/@PostMapping("/bind")public Result register(@RequestBody SocialBindVO user) {return sysUserService.doPostSignUp(user);}/*** 取消授权登录** @param source 平台* @param token  token* @return* @throws IOException*/@RequestMapping("/revoke/{source}/{token}")public Object revokeAuth(@PathVariable("source") String source, @PathVariable("token") String token) throws IOException {Result result = userSocialService.unBind(source, token);AuthRequest authRequest = getAuthRequest(source);try {authRequest.revoke(AuthToken.builder().accessToken(token).build());} catch (Exception e) {e.printStackTrace();}return result;}/*** 刷新Token** @param source* @param token* @return*/@RequestMapping("/refresh/{source}")public Object refreshAuth(@PathVariable("source") String source, String token) {AuthRequest authRequest = getAuthRequest(source);return   authRequest.refresh(AuthToken.builder().refreshToken(token).build());}/*** 用户信息** @param sysUser* @param result* @return*/private Result<JSONObject> userInfo(SysUser sysUser, Result<JSONObject> result) {String syspassword = sysUser.getPassword();String username = sysUser.getUsername();// 生成tokenString token = JwtUtil.sign(username, syspassword);// 设置token缓存有效时间redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME * 2 / 1000);// 获取用户部门信息JSONObject obj = new JSONObject();List<SysDepart> departs = sysDepartService.queryUserDeparts(sysUser.getId());obj.put("departs", departs);if (departs == null || departs.size() == 0) {obj.put("multi_depart", 0);} else if (departs.size() == 1) {sysUserService.updateUserDepart(username, departs.get(0).getOrgCode());obj.put("multi_depart", 1);} else {obj.put("multi_depart", 2);}obj.put("token", token);obj.put("userInfo", sysUser);result.setResult(obj);result.success("登录成功");return result;}/*** 根据具体的授权来源,获取授权请求工具类** @param source* @return*/private AuthRequest getAuthRequest(String source) {AuthRequest authRequest = null;switch (source) {case "dingtalk":authRequest = new AuthDingTalkRequest(AuthConfig.builder().clientId("").clientSecret("").redirectUri(callBackBaseUrl + "/dingtalk").build());break;case "baidu":authRequest = new AuthBaiduRequest(AuthConfig.builder().clientId("").clientSecret("").redirectUri(callBackBaseUrl + "/baidu").build());break;case "github":authRequest = new AuthGithubRequest(AuthConfig.builder().clientId("").clientSecret("").redirectUri(callBackBaseUrl + "/github").build());break;case "gitee":authRequest = new AuthGiteeRequest(AuthConfig.builder().clientId("").clientSecret("").redirectUri(callBackBaseUrl + "/gitee").build());break;case "weibo":authRequest = new AuthWeiboRequest(AuthConfig.builder().clientId("微博的APP ID").clientSecret("微博的APP Key").redirectUri(callBackBaseUrl + "/weibo").build());break;case "coding":authRequest = new AuthCodingRequest(AuthConfig.builder().clientId("").clientSecret("").redirectUri(callBackBaseUrl + "/coding").build());break;case "tencentCloud":authRequest = new AuthTencentCloudRequest(AuthConfig.builder().clientId("").clientSecret("").redirectUri(callBackBaseUrl + "/tencentCloud").build());break;case "oschina":authRequest = new AuthOschinaRequest(AuthConfig.builder().clientId("").clientSecret("").redirectUri(callBackBaseUrl + "/oschina").build());break;case "alipay":// 支付宝在创建回调地址时,不允许使用localhost或者127.0.0.1,所以这儿的回调地址使用的局域网内的ipauthRequest = new AuthAlipayRequest(AuthConfig.builder().clientId("").clientSecret("").alipayPublicKey("").redirectUri(callBackBaseUrl + "/alipay").build());break;case "qq":authRequest = new AuthQqRequest(AuthConfig.builder().clientId("填写QQ的APP ID").clientSecret("填写QQ的APP Key").redirectUri(callBackBaseUrl + "/qq").build());break;case "wechat":authRequest = new AuthWeChatRequest(AuthConfig.builder().clientId("123").clientSecret("123").redirectUri(callBackBaseUrl + "/wechat").build());break;case "csdn":authRequest = new AuthCsdnRequest(AuthConfig.builder().clientId("").clientSecret("").redirectUri(callBackBaseUrl + "/csdn").build());break;case "taobao":authRequest = new AuthTaobaoRequest(AuthConfig.builder().clientId("").clientSecret("").redirectUri(callBackBaseUrl + "/taobao").build());break;case "google":authRequest = new AuthGoogleRequest(AuthConfig.builder().clientId("").clientSecret("").redirectUri(callBackBaseUrl + "/google").build());break;case "facebook":authRequest = new AuthFacebookRequest(AuthConfig.builder().clientId("").clientSecret("").redirectUri(callBackBaseUrl + "/facebook").build());break;case "douyin":authRequest = new AuthDouyinRequest(AuthConfig.builder().clientId("").clientSecret("").redirectUri(callBackBaseUrl + "/douyin").build());break;case "linkedin":authRequest = new AuthLinkedinRequest(AuthConfig.builder().clientId("").clientSecret("").redirectUri(callBackBaseUrl + "/linkedin").build());break;case "microsoft":authRequest = new AuthMicrosoftRequest(AuthConfig.builder().clientId("").clientSecret("").redirectUri(callBackBaseUrl + "/microsoft").build());break;case "mi":authRequest = new AuthMiRequest(AuthConfig.builder().clientId("").clientSecret("").redirectUri(callBackBaseUrl + "/mi").build());break;case "toutiao":authRequest = new AuthToutiaoRequest(AuthConfig.builder().clientId("").clientSecret("").redirectUri(callBackBaseUrl + "/toutiao").build());break;case "teambition":authRequest = new AuthTeambitionRequest(AuthConfig.builder().clientId("").clientSecret("").redirectUri(callBackBaseUrl + "/teambition").build());break;case "pinterest":authRequest = new AuthPinterestRequest(AuthConfig.builder().clientId("").clientSecret("").redirectUri(callBackBaseUrl + "/pinterest").build());break;case "renren":authRequest = new AuthRenrenRequest(AuthConfig.builder().clientId("").clientSecret("").redirectUri(callBackBaseUrl + "/teambition").build());break;case "stackoverflow":authRequest = new AuthStackOverflowRequest(AuthConfig.builder().clientId("").clientSecret("").redirectUri(callBackBaseUrl + "/login_success").stackOverflowKey("").build());break;case "huawei":authRequest = new AuthHuaweiRequest(AuthConfig.builder().clientId("").clientSecret("").redirectUri(callBackBaseUrl + "/huawei").build());break;case "wechatEnterprise":authRequest = new AuthHuaweiRequest(AuthConfig.builder().clientId("").clientSecret("").redirectUri(callBackBaseUrl + "/wechatEnterprise").agentId("").build());break;case "kujiale":authRequest = new AuthKujialeRequest(AuthConfig.builder().clientId("").clientSecret("").redirectUri(callBackBaseUrl + "/kujiale").build());break;case "gitlab":authRequest = new AuthGitlabRequest(AuthConfig.builder().clientId("").clientSecret("").redirectUri(callBackBaseUrl + "/gitlab").build());break;case "meituan":authRequest = new AuthMeituanRequest(AuthConfig.builder().clientId("").clientSecret("").redirectUri(callBackBaseUrl + "/meituan").build());break;case "eleme":authRequest = new AuthElemeRequest(AuthConfig.builder().clientId("").clientSecret("").redirectUri(callBackBaseUrl + "/eleme").build());break;case "twitter":authRequest = new AuthTwitterRequest(AuthConfig.builder().clientId("").clientSecret("").redirectUri(callBackBaseUrl + "/twitter").build());break;default:break;}if (null == authRequest) {throw new AuthException("未获取到有效的Auth配置");}return authRequest;}
}

3 前端Vue

3.2 Vue登录界面

<template><div class="main"><a-form :form="form" class="user-layout-login" ref="formLogin" id="formLogin"><div class="user-login-other"><span>其他登陆方式</span><a><a-icon class="item-icon" @click="showOauthModal('qq')" type="qq"></a-icon></a><a><a-icon class="item-icon" @click="showOauthModal('wechat')"  type="wechat"></a-icon></a><a><a-icon class="item-icon" @click="showOauthModal('weibo')"  type="weibo-circle"></a-icon></a><!-- <router-link class="register" :to="{ name: 'register' }">注册账户</router-link>--></div></a-form><a-modaltitle="第三方授权登录":visible="aouthVisible":confirmLoading="aouthLoading"width="650px":closable="false":maskClosable="false"><template slot="footer"><a-button type="danger" @click="handleAaouthCancel">取消授权</a-button></template><iframe  :id="aouthId" :src="aouthUrl" frameborder="0" width="100%" height="350px" scrolling="auto"></iframe></a-modal></div>
</template><script>import api from '@/api'import Vue from 'vue'import { ACCESS_TOKEN ,ENCRYPTED_STRING} from "@/store/mutation-types"import JGraphicCode from '@/components/jeecg/JGraphicCode'import { postAction } from '@/api/manage'import { getAction } from '@/api/manage'import store from '@/store/'import { USER_INFO } from "@/store/mutation-types"import { message } from 'ant-design-vue';export default {,data () {aouthVisible: false,aouthLoading: false,aouthUrl: "/oauth/render/qq",aouthId: "https://www.baidu.com",}},created () {const key = getUrlKey('key');if (key != null && key !== '') {this.socialLogin(key);console.log("请求数据" + key);} else {console.log("没有请求数据")}Vue.ls.remove(ACCESS_TOKEN)},methods: {...mapActions([ "SocialLogin" ]),showOauthModal(type) {let obj = {};//请求第三方授权登录postAction('/oauth/render/'+type, obj).then(res => {if (res.success) {if (!res.result.token) {// this.aouthUrl = res.result;// this.aouthVisible = true;window.location.href = res.result;console.log(type + "请求第三方登录:" + JSON.stringify(res));}} else {message.error('打开第三方登录失败');}});},handleAaouthCancel(e) {console.log('Clicked cancel button');this.aouthVisible = false;},socialLogin(key) {let that=this;const socialBind = {key: key};that.SocialLogin(socialBind).then((res) => {this.departConfirm(res)}).catch((err) => {that.requestFailed(err);});/*            postAction("/oauth/user_info", socialBind).then((res) => {console.log('提交的信息',JSON.stringify(res))if (!res.success) {this.requestFailed(res.message)} else {const userInfo = res.result.userInfo;Vue.ls.set(USER_INFO, userInfo, 7 * 24 * 60 * 60 * 1000);store.commit('SET_INFO', userInfo);Vue.ls.set(ACCESS_TOKEN, result.token, 7 * 24 * 60 * 60 * 1000)this.$router.push({ name: "dashboard" })this.departConfirm(res);}})*/}},function getUrlKey(name) {//解析URL中的keytry {return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.href) || [''])[1].replace(/\+/g, '%20')) || null;}catch (e) {return null;}
}}
</script><style lang="scss" scoped>.user-layout-login {label {font-size: 14px;}.getCaptcha {display: block;width: 100%;height: 40px;}.forge-password {font-size: 14px;}button.login-button {padding: 0 15px;font-size: 16px;height: 40px;width: 100%;}.user-login-other {text-align: left;margin-top: 24px;line-height: 22px;.item-icon {font-size: 24px;color: rgba(0,0,0,.2);margin-left: 16px;vertical-align: middle;cursor: pointer;transition: color .3s;&:hover {color: #1890ff;}}.register {float: right;}}}</style>
<style>.valid-error .ant-select-selection__placeholder{color: #f5222d;}
</style>

3.2 Vue绑定界面

<template><div class="main user-layout-register"><h3><span>第三方绑定账户</span></h3><a-form ref="formRegister" :autoFormCreate="(form)=>{this.form = form}" id="formRegister"><a-form-itemfieldDecoratorId="username"><a-input size="large" type="text" autocomplete="false" placeholder="请输入用户名"></a-input></a-form-item><a-form-itemfieldDecoratorId="password"><a-input size="large" type="password" autocomplete="false" placeholder="确认密码"></a-input></a-form-item><a-form-item><a-buttonsize="large"type="primary"htmlType="submit"class="register-button":loading="registerBtn"@click.stop.prevent="handleSubmit":disabled="registerBtn">绑定账户</a-button><router-link class="login" :to="{ name: 'login' }">返回登录</router-link><router-link class="login" :to="{ name: 'register' }" style="float: right;margin-right: 10px">注册账户</router-link></a-form-item></a-form></div>
</template><script>import {mixinDevice} from '@/utils/mixin.js'import {getUrlKey} from '@/components/_util/StringUtil.js'import {getAction, postAction} from '@/api/manage'export default {name: "SocialBind",components: {},mixins: [mixinDevice],data() {return {form: {username: '',password: '',key: ''},registerBtn: false}},methods: {handleSubmit(){const _this = thisconst key = getUrlKey('key');console.log("地址中的key:"+key)this.form.validateFields((err, values) => {if (!err) {const socialBind = {username:values.username,password:values.password,key: key};console.log('提交的信息',JSON.stringify(socialBind))postAction("/oauth/bind", socialBind).then((res) => {if (!res.success) {this.bindFailed(res.message)} else {this.$notification.open({message: '成功',description:'社交账号绑定成功,2秒后返回登录页面',duration: 2,});setTimeout(() => {this.$router.push({name: 'login', params: {...values}})}, 2000)}})}});},bindFailed(message) {this.$notification['error']({message: "绑定失败",description: message,duration: 2,});},}}
</script>
<style lang="scss">.user-register {&.error {color: #ff0000;}&.warning {color: #ff7e05;}&.success {color: #52c41a;}}.user-layout-register {.ant-input-group-addon:first-child {background-color: #fff;}}
</style>
<style lang="scss" scoped>.user-layout-register {& > h3 {font-size: 16px;margin-bottom: 20px;}.getCaptcha {display: block;width: 100%;height: 40px;}.register-button {width: 100%;}.login {float: right;line-height: 40px;}}
</style>

参考

1.Spring Boot 快速集成第三方登录功能:https://xkcoding.com/2019/05/22/spring-boot-login-with-oauth.html

2.JustAuth GitHub地址:https://github.com/justauth/JustAuth

spring boot+Vue整合第三方登录JustAuth相关推荐

  1. Spring Boot 快速集成第三方登录功能

    Spring Boot 快速集成第三方登录功能 前言 此 demo 主要演示 Spring Boot 项目如何使用 史上最全的第三方登录工具 - JustAuth 实现第三方登录,包括 QQ 登录.G ...

  2. Spring Boot 接入 GitHub 第三方登录,只要两行配置!

    点击上方 好好学java ,选择 星标 公众号重磅资讯,干货,第一时间送达 今日推荐:14 个 github 项目!个人原创100W +访问量博客:点击前往,查看更多 本文地址:https://www ...

  3. Spring Boot + Vue前后端分离项目,Maven自动打包整合

    前言 现在各类项目为了降低项目.服务模块间的高度耦合性,提出了"前后端分离",而前后端分离的项目该如何打包呢? 一般的做法是前端项目打包完,将打包文件手动复制到后端项目工程的src ...

  4. 读书笔记《Spring Boot+Vue全栈开发实战》(下)

    本书将带你全面了解Spring Boot基础与实践,带领读者一步步进入 Spring Boot 的世界. 前言 第九章 Spring Boot缓存 第十章 Spring Boot安全管理 第十一章 S ...

  5. 前后端分离 Spring Boot + Vue 开发网易云QQ音乐(附源码)!

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者|xiangzhihong segmentfault.com/ ...

  6. 牛皮!竟然有大佬基于 Spring Boot + Vue 开发了一套网易云amp;QQ音乐(附源码)。。。...

    来源:segmentfault.com/a/1190000021376934 # 前言 虽然 B/S 是目前开发的主流,但是 C/S 仍然有很大的市场需求.受限于浏览器的沙盒限制,网页应用无法满足某些 ...

  7. Spring Boot + Vue.js 实现前后端分离(附源码)

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者: 梁小生0101 链接:juejin.im/post/5c6 ...

  8. 《Spring Boot+Vue全栈开发实战》读书笔记

    写在前面 嗯,回家处理一些事,所以离职了,之前的公司用开源技术封装了一套自己的低代码平台,所以之前学的spring Boot之类的东西都忘了很多,蹭回家的闲暇时间复习下. 笔记整体以 Spring B ...

  9. Spring Boot Vue Element入门实战(完结)

    最近给朋友做一个大学运动会管理系统,用作教学案例,正好自己也在自学VUE,决定用spring boot vue做一个简单的系统.vue这个前端框架很火,他和传统的Jquery 编程思路完全不一样,Jq ...

最新文章

  1. CUDNN_STATUS_NOT_INITIALIZED解决汇总
  2. Python:序列的copy() 方法和 copy 模块
  3. 利用Chrome开发者工具分析C4C Opportunity搜索的前端性能
  4. C语言 >> 右移位运算符的原理和一些概念
  5. 天线发射功率计算公式_增加发射功率,提高接收灵敏度就能提高通信距离吗?...
  6. python如何执行代码漏洞_在漏洞利用Python代码真的很爽
  7. 社交网络分析初步学习1.md
  8. cryptojs php 互通_AES 加密解密 CryptoJS + php 方案
  9. word 宏相关代码集合
  10. 【数据库】三级模式两级映射详解
  11. 一个小妙招能让你在服装上省下好多rmb
  12. 李群和李代数以及李代数求导(扰动模型)
  13. 最近很火的微信炸屎功能该怎么用?
  14. 工作十年,你的职场核心竞争力在哪里
  15. excel画图,折线
  16. unity基础学习之基础语义
  17. C语言输出教学日历表
  18. java开发工程师的晋升路径_Java开发工程师职业发展及晋升路线图
  19. Linux tar 解压缩工具
  20. 写给兄弟连学员的第三封信 ——学习这点事 李 明

热门文章

  1. 安装安全类软件进行了android签名漏洞修补,魅蓝Note刷机教程 升级固件方法详解...
  2. 基于华为云ModelArts平台利用MobileNetV2算法实现5类花卉分类
  3. 程序员百宝箱---搭建自己专属的在线工具集
  4. hive 十六进制转十进制_Hive内置函数详解【转】
  5. 18 11 20 网络通信 ----多任务---- 携程 ----生成器
  6. 西安电子科技大学MSP 3月校园活动总结
  7. 跟着开涛学SpringMVC
  8. 同时删除多个 Excel 文档前几个工作表
  9. 使用PIL为图片添加水印[python]
  10. 2022ISCC PWN