29.第三方登录

news2024/11/25 12:37:51

1►第三方登录

当今社会,微信登录、QQ登录、抖音登录等等三方登录已经层出不穷,学会三方登录势在必行。

微信登录要认证开发者,必须为企业,个人不行,而且还要交300块钱。

QQ登录也要申请、微博登录也要申请。

还好Gitee给力,申请轻轻松松,谁都能轻松让Gitee作为第三方登录,此次我们就讲解Gitee来登录ry。其实其他的登录也是基本上一样的。

2►JustAuth 奥义·穿风刺

JustAuth能让我们第三方登录写少一些代码,它包装了国内外30多种三方登录。

学习JustAuth网站:

https://mp.weixin.qq.com/s?__biz=MzA3NDk3OTIwMg==&mid=2450633106&idx=1&sn=131e39d52347dffefbd4227b18b794bf&chksm=8892937fbfe51a69950cb0769e2b22d04217254b0e79cdcee4204aedb2007627ab6511b58355&token=29120304&lang=zh_CN#rd

https://justauth.wiki/guide/quickstart/how-to-use/#%E4%BD%BF%E7%94%A8%E6%AD%A5%E9%AA%A4

使用步骤

使用JustAuth总共分三步(这三步也适合于JustAuth支持的任何一个平台):

1、申请注册第三方平台的开发者账号。

我们找到gitee的设置,进入第三方应用,如下:

出来界面如下:

我现在是已经新建好了应用,大家是没有ruoyi-test。大家可以新建自己的应用:

 

应用主页随便填一个自己的应用页面即可。但是应用回调不能乱填,当我们gitee登录成功之后,gitee会自动跳转到应用回调地址,并且gitee会带上code,利用code可以得到所登录gitee用户信息。 

2、创建第三方平台的应用,获取配置信息(accessKey, secretKey, redirectUri)。

上面我们已经创建了应用,自然有了这三个值。

3、使用该工具实现授权登陆。

利用工具先要引入依赖:

 <dependency>            <groupId>me.zhyd.oauth</groupId>            <artifactId>JustAuth</artifactId>            <version>1.16.5</version>        </dependency>

依赖引入到核心框架(framework)下。

接下来改login.vue,如下:

 <el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form">
      ...省略其他代码
      <el-form-item style="width:100%;">
        <el-button
          :loading="loading"
          size="medium"
          type="primary"
          style="width:100%;"
          @click.native.prevent="handleLogin"
        >
          <span v-if="!loading">登 录</span>
          <span v-else>登 录 中...</span>

        </el-button>
        <div style="float: right;" v-if="register">
          <router-link class="link-type" :to="'/register'">立即注册</router-link>
        </div>
        <div style="width: 32px;height: 32px;margin-top: 5px;cursor: pointer;" title="利用Gitee登录" @click="giteeLogin">
          <img style="height: 100%;width: 100%;" src="../assets/logo/gitee.png">
        </div>
      </el-form-item>
    </el-form>

以上,我们添加的代码是:

有了该代码,页面呈现的样子是: 

关于图片LOGO下载地址请去随便找一个,或者群文件找找。然后我们看一下点击事件:

 giteeLogin() {
      PreLoginByGitee().then(res => {
        Cookies.set("user-uuid", res.uuid)
        window.location = res.authorizeUrl
      })
    },

以上是在methods中,我们看到直接请求了PreLoginByGitee:


export function PreLoginByGitee() {
  return request({
    url: '/PreLoginByGitee',
    headers: {
      isToken: false
    },
    method: 'get',
  })
}

对应的后端接口:

在ruoyi-admin下创建login包,专门存放第三方登录文件

 @GetMapping("/PreLoginByGitee")
    public AjaxResult PreLoginByGitee() {
        AjaxResult ajax = AjaxResult.success();
        AuthRequest authRequest = new AuthGiteeRequest(AuthConfig.builder()
                .clientId("1712ae8e8105c0005da36339ed72c1a6aae86322fc64d431dadcaa275a14be45")
                .clientSecret("87fb8f83efc04fcd85696d5461c80ce6f98c94845539f9612024e81302111a05")
                .redirectUri("http://localhost/callback")
                .build());
        String uuid = IdUtils.fastUUID();
        String authorizeUrl = authRequest.authorize(uuid);
        //存储
        ajax.put("authorizeUrl", authorizeUrl);
        ajax.put("uuid", uuid);
        return ajax;
    }

以上的代码是生成跳转路径。生成一个gitee的路径,在该页面gitee只要登录完成,gitee程序会自动跳转到我们之前设置好的回调地址。这里我们发现我们一直拿着一个uuid在传来传去,还传去了前端,它有什么鸟用呢?

authRequest.authorize(uuid)用到了uuid,并且后面要执行:

authRequest.login(AuthCallback.builder().state(uuid).code(code).build());

要保证俩uuid为同一个,所以uuid才传来传去。

关于本篇文章,文字有点难以描述,请大家看视频。

上面window.location = res.authorizeUrl让我们进入了如下界面:

图片

只要我们登陆好gitee,gitee会自动跳转到我们的回调地址。此时回调到了前端的下面的路由:

图片

我们还提前准备好了组件:

<template>
  <div v-loading="loading" style="height: 100%;width: 100%;">
    正在加载中...
  </div>
</template>

<script>

import Cookies from "js-cookie";

export default {
  name: "loginByGitee",
  data() {
    return {
      loading: true
    }
  },
  mounted() {
    this.loading = true;
    console.log("uuid", Cookies.get("user-uuid"))
    const formBody = {
      uuid: Cookies.get("user-uuid"),
      code: this.$route.query.code
    }
    this.$store.dispatch("LoginByGitee", formBody).then(() => {
      this.$router.push({path: this.redirect || "/"}).catch(() => {
      });
    }).catch(() => {
      this.loading = false;
    });
  }
}
</script>

<style scoped>

</style>

配置了组件,再配置路由

从上面可以看到,又带着了uuid,执行LoginByGitee方法,如下:

    LoginByGitee({commit}, body) {      return new Promise((resolve, reject) => {        loginByGitee(body.code, body.uuid).then(res => {          setToken(res.token)          commit('SET_TOKEN', res.token)          resolve()        }).catch(error => {          reject(error)        })      })    },

继续追代码:

export function loginByGitee(code, uuid) {  const data = {    code,    source: "Gitee",    uuid  }  return request({    url: '/loginByGitee',    headers: {      isToken: false    },    method: 'post',    data: data  })}

追到底了,调用的后端的:

 @PostMapping("/loginByGitee")
    public AjaxResult loginByGitee(@RequestBody LoginByOtherSourceBody loginByOtherSourceBody) {
        AjaxResult ajax = AjaxResult.success();
        String token = loginService
                .loginByOtherSource(loginByOtherSourceBody.getCode(), loginByOtherSourceBody.getSource(), loginByOtherSourceBody.getUuid());
        ajax.put(Constants.TOKEN, token);
        return ajax;
    }

补充LoginByOtherSourceBody实体类

package com.ruoyi.common.core.domain.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class LoginByOtherSourceBody {
    private String code;
    private String source;
    private String uuid;
}

service层:

 public String loginByOtherSource(String code, String source, String uuid) {
        //先到数据库查询这个人曾经有没有登录过,没有就注册
        // 创建授权request
        AuthRequest authRequest = new AuthGiteeRequest(AuthConfig.builder()
                .clientId("1712ae8e8105c0005da36339ed72c1a6aae86322fc64d431dadcaa275a14be45")
                .clientSecret("87fb8f83efc04fcd85696d5461c80ce6f98c94845539f9612024e81302111a05")
                .redirectUri("http://localhost/callback")
                .build());
        AuthResponse<AuthUser> login = authRequest.login(AuthCallback.builder().state(uuid).code(code).build());
        System.out.println(login);
        //先查询数据库有没有该用户
        AuthUser authUser = login.getData();
        SysUser sysUser = new SysUser();
        sysUser.setUserName(authUser.getUsername());
        sysUser.setSource(authUser.getSource());
        List<SysUser> sysUsers = userService.selectUserListNoDataScope(sysUser);
        if (sysUsers.size() > 1) {
            throw new ServiceException("第三方登录异常,账号重叠");
        } else if (sysUsers.size() == 0) {
            //相当于注册
            sysUser.setNickName(authUser.getNickname());
            sysUser.setAvatar(authUser.getAvatar());
            sysUser.setEmail(authUser.getEmail());
            sysUser.setRemark(authUser.getRemark());
            userService.registerUserAndGetUserId(sysUser);
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(sysUser.getUserName(), Constants.REGISTER,
                    MessageUtils.message("user.register.success")));
        } else {
            sysUser = sysUsers.get(0);
        }
        AsyncManager.me().execute(AsyncFactory.recordLogininfor(sysUser.getUserName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
        //注册成功或者是已经存在的用户
        LoginUser loginUser =
                new LoginUser(sysUser.getUserId(), sysUser.getDeptId(), sysUser, permissionService.getMenuPermission(sysUser));
        recordLoginInfo(loginUser.getUserId());
        // 生成token
        return tokenService.createToken(loginUser);
    }

似乎如此就完事了。但实际上有很多细节我都没说。在视频里面说。

在SysUser实体类添加private String source;属性

1.在数据库中添加source字段

2.xml各个sql添加source

service添加方法

为了去掉权限的限制

重写插入方法,让他放回long类型

 其实sql是一样的,只是为了返回的类型不同

细节1:前端白名单放行:

const whiteList = ['/login', "/callback", '/auth-redirect', '/bind', '/register']

细节2:字段source。如下代码可以获得登录source:

AuthUser authUser = login.getData();

source表示登录平台,如微信登录,支付宝登录,因为要确定用户的唯一性。username在不同的平台可能会重复,但是username+source就不会重复了。

细节3:新写了一个查询方法,如下:

userService.selectUserListNoDataScope(sysUser);
    @Override    public List<SysUser> selectUserListNoDataScope(SysUser user) {        return userMapper.selectUserList(user);    }

新重写一个查询的原因是原来的的方法有数据权限:

图片

细节4:后端安全配置放行了若干接口:

                .antMatchers("/login", "/register", "/captchaImage", "/loginByGitee", "/PreLoginByGitee").anonymous()

细节5:当我们第一次登录成功,什么权限都没有,需要admin设置一下权限,或者在注册的时候给新用户一个“普通角色”。

细节6:新登录用户,头像根本显示不了,改成如下就能显示了【文件user.js】:

          let avatar;          if (user.avatar == "" || user.avatar == null) {            avatar = require("@/assets/images/profile.jpg")          } else if (user.avatar.startsWith("http")) {            avatar = user.avatar          } else {            avatar = process.env.VUE_APP_BASE_API + user.avatar;          }

其他细节不再赘述。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1208520.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

为什么重写equals方法必须重写hashcode方法

在Java中&#xff0c;重写equals()方法的同时也应该重写hashCode()方法&#xff0c;这是因为这两个方法在 Java 中是有关联的&#xff0c;而且它们一起影响着集合类的行为。 Java中的hashCode()方法用于返回对象的哈希码&#xff0c;而equals()方法用于比较两个对象是否相等。…

[文件读取]webgrind 文件读取 (CVE-2018-12909)

1.1漏洞描述 漏洞编号CVE-2018-12909漏洞类型文件读取漏洞等级⭐⭐⭐漏洞环境VULFOCUS攻击方式 1.2漏洞等级 高危 1.3影响版本 Webgrind 1.5版本 1.4漏洞复现 1.4.1.基础环境 1.4.2.前提 网站后台地址&#xff1a; 后台管理账密&#xff1a; 后台登录地址 1.5深度利用 …

【rl-agents代码学习】02——DQN算法

文章目录 Highway-env Intersectionrl-agents之DQN*Implemented variants*:*References*:Query agent for actions sequence探索策略神经网络实现小结1 Record the experienceReplaybuffercompute_bellman_residualstep_optimizerupdate_target_network小结2 exploration_polic…

spring 整合 JUnit

大家好&#xff0c;本篇博客我们通过spring来整合JUnitt单元测试框架。 在之前篇章的测试方法中&#xff0c;几乎都能看到以下的两行代码&#xff1a; ApplicationContext context new ClassPathXmlApplicationContext("xxx.xml"); Xxxx xxx context.getBean(Xxx…

ppt画思路图 流程图 医学药学生画图素材

关注微信&#xff0c;回复: 素材 &#xff0c;即可领取

EtherNET转Profibus网关使用 AB PLC的配置方法

兴达易控EtherNET转Profibus网关&#xff08;XD-EPPB20&#xff09;是一款功能强大的通讯设备&#xff0c;具备Profibus从站功能。它的主要作用是将EtherNET/IP设备无缝接入到PROFIBUS网络中。通过连接到Profibus总线&#xff0c;它可以作为从站使用&#xff0c;并且通过连接到…

作为8年老测试告诉你学会这样写性能测试方案,阿里p8都直呼内行

订单处理服务的性能测试方案V1.0 一、需求背景 在设计评审之后&#xff0c;开发在不知道服务性能瓶颈&#xff0c;需要测试协助定位服务的性能瓶颈&#xff0c;需要测试模拟一定时间之内设计并发用户同时向系统发出请求&#xff0c;检测出系统的响应能力&#xff0c;包括响应…

企业数字化建设之——老板关注的IT指标有哪些 ?

投资回报ROI | 商业价值 | 系统可用性 | 业务的参与程度 | 技术债务指数 降本&#xff0c;增效是IT部门工作的永恒话题 &#xff0c;降低成本 &#xff0c;增加效益 &#xff0c;降本增效的工作方向&#xff1a; 1 年初KPI目标、目标完成情况、关键证据、公司主线工作…

腾讯云2核4G和4核8G服务器配置5年租用价格表

腾讯云服务器网整理五年云服务器活动 txyfwq.com/go/txy 配置可选2核4G和4核8G&#xff0c;公网带宽可选1M、3M或5M&#xff0c;系统盘为50G高性能云硬盘&#xff0c;标准型S5实例CPU采用主频2.5GHz的Intel Xeon Cascade Lake或者Intel Xeon Cooper Lake处理器&#xff0c;睿频…

Java的XWPFTemplate word生成列表

Java的XWPFTemplate工具类导出word.docx的使用_xwpftemplate 语法_youmdt的博客-CSDN博客 如果是表格的列表参考上面这篇文章即可&#xff0c;比较复杂的列表遍历暂时还没找到方法&#xff0c;只能手动创建表格了 上面是模板&#xff0c;非常简单&#xff0c;以为我们是要自己创…

SELF-AUGMENTED MULTI-MODAL FEATURE EMBEDDING

two embeddings f o r g _{org} org​ and f a u g _{aug} aug​ are combined using a gating mechanism 作者未提供代码

修改Conda虚拟环境默认位置失败——解决方案

修改虚拟环境默认安装位置依然❌ 偶然遇到conda创建虚拟环境创建失败的问题&#xff0c;按照教程修改.condarc文件中 envs_dirs:- E:\miniconda3\envs依然无法更改虚拟环境默认安装位置。 解决方案 找到想更改的虚拟环境文件位置&#xff0c;检查确认是否有写入权限&#…

C++ builder 常见问题汇总

1、CB静态编译设置 2、CB10.3设置经典编译器&#xff08;用于解决10.3弹出代码提示慢&#xff09; 3、CBuilder生成Release版本 &#xff1a; project->Options->CCompiler->Build Configuration 选择 Release project->Options->CLinker中取消Use dynamic RTL…

upload-labs关卡5(点和空格绕过)通关思路

文章目录 前言一、回顾上一关知识点二、靶场第五关通关思路1.看源代码2.点和空格绕过3、验证上传 总结 前言 此文章只用于学习和反思巩固文件上传漏洞知识&#xff0c;禁止用于做非法攻击。注意靶场是可以练习的平台&#xff0c;不能随意去尚未授权的网站做渗透测试&#xff0…

MES系统如何改进生产管理?

伴随机械制造业行业竞争逐渐加剧&#xff0c;越来越多企业意识到MES系统的重要性&#xff0c;慢慢积极主动把握和实施MES系统。可是纵观绝大部分企业或者MES生产商&#xff0c;对MES的掌握依然存在比较大的分歧。 有一些人说MES系统是企业信息化构建的中枢神经&#xff0c;也有…

HTML转PDF模板

一、准备pom依赖 <dependency><groupId>com.itextpdf</groupId><artifactId>html2pdf</artifactId><version>1.0.2</version></dependency><dependency><groupId>org.freemarker</groupId><artifactId&g…

LockBit3.0的字符串解密方法

LockBit 与大多数勒索黑客团体一样以勒索软件即服务 (RaaS) 模式运行,该组织于 2019 年 9 月首次被观察到,此后发展为了今年最主要的勒索软件团伙,甚至超过了Conti、Hive等其他知名团体。据泄露数据站点的数据统计表明,LockBit占2022年第一季度所有与勒索软件相关的泄露事件…

基于自私羊群算法优化概率神经网络PNN的分类预测 - 附代码

基于自私羊群算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于自私羊群算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于自私羊群优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神…

基于闪电搜索算法优化概率神经网络PNN的分类预测 - 附代码

基于闪电搜索算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于闪电搜索算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于闪电搜索优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神…

【开源】基于JAVA的超市商品管理系统

目录 一、摘要1.1 简介1.2 项目详细录屏 二、研究内容2.1 数据中心模块2.2 超市区域模块2.3 超市货架模块2.4 商品类型模块2.5 商品档案模块 三、系统设计3.1 用例图3.2 时序图3.3 类图3.4 E-R图 四、系统实现4.1 登录4.2 注册4.3 主页4.4 超市区域管理4.5 超市货架管理4.6 商品…