若依实现第三方登录,史上最全保姆级教程

这篇具有很好参考价值的文章主要介绍了若依实现第三方登录,史上最全保姆级教程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

第一步:去申请对应平台的appid

1.1:登录Gitee

1.2:点击头像->点击设置

若依 第三方登录,java

1.3:点击第三方应用->点击创建应用

若依 第三方登录,java

1.4:填写基本信息,参照我的这个,应用回调地址我写了两个,一个本地测试用,一个发布到环境上使用,自己测试的时候写一个就行了,这个是第三方授权后的回调地址

若依 第三方登录,java

第二步:基本环境搭建

2.1:需要引入的依赖,在ruoyi-common下引入依赖

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
</dependency>

2.2:数据表创建,为了以后可以拓展其他平台,我们创建第三方授权表

create table sys_user_third_account(
    id                   bigint auto_increment
        primary key,
    user_id              bigint                  null comment '对应sys_user的用户id',
    third_unique_account varchar(100)            null comment '第三方唯一用户id,可以是giteeId/QQ的openid,或苹果id,',
    third_unique_name    varchar(30)             null comment '第三方用户名',
    third_unique_avatar  varchar(300)            null comment '第三方用户头像url',
    bind_type            varchar(5)              null comment '标识第三方类型,1.gitee_id',
    bind_flag            varchar(2)  default '0' null comment '标识是否绑定:值集(user_third_status)',
    bind_date            datetime                null comment '绑定时间',
    create_by            varchar(64) default ''  null comment '创建者',
    create_time          datetime                null comment '创建时间',
    update_by            varchar(64) default ''  null comment '更新者',
    update_time          datetime                null comment '更新时间',
    del_flag             char        default '0' null comment '删除标志(0代表存在 2代表删除)'
)  comment '第三方账户绑定' charset = utf8mb4;

2.3:第三步,创建对应的实体类,mapper,service,这里可以直接通过若依的代码生产器进行生成,我这里也给你提供好了

2.3.1:实体类

package com.ruoyi.system.domain;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.core.domain.BaseEntity;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

import java.util.Date;

/**
 * @author xiao_he
 */
public class SysUserThirdAccount extends BaseEntity {
    private static final long serialVersionUID = 1L;

    /**
     * $column.columnComment
     */
    private Long id;

    /**
     * 对应sys_user的用户id
     */
    private Long userId;

    /**
     * 第三方唯一用户id,可以是微信的openid,可以是QQ的openid,抑或苹果id,
     */
    private String thirdUniqueAccount;

    /**
     * 第三方用户名
     */
    private String thirdUniqueName;

    /**
     * 第三方用户头像url
     */
    private String thirdUniqueAvatar;

    /**
     * 标识第三方类型,1.gitee_id
     */
    private String bindType;

    /**
     * 标识是否绑定,1绑定,2解绑
     */
    private String bindFlag;

    /**
     * 绑定时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date bindDate;

    /**
     * 删除标志(0代表存在 2代表删除)
     */
    private String delFlag;

    public void setId(Long id) {
        this.id = id;
    }

    public Long getId() {
        return id;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    public Long getUserId() {
        return userId;
    }

    public void setThirdUniqueAccount(String thirdUniqueAccount) {
        this.thirdUniqueAccount = thirdUniqueAccount;
    }

    public String getThirdUniqueAccount() {
        return thirdUniqueAccount;
    }

    public void setThirdUniqueName(String thirdUniqueName) {
        this.thirdUniqueName = thirdUniqueName;
    }

    public String getThirdUniqueName() {
        return thirdUniqueName;
    }

    public void setThirdUniqueAvatar(String thirdUniqueAvatar) {
        this.thirdUniqueAvatar = thirdUniqueAvatar;
    }

    public String getThirdUniqueAvatar() {
        return thirdUniqueAvatar;
    }

    public void setBindType(String bindType) {
        this.bindType = bindType;
    }

    public String getBindType() {
        return bindType;
    }

    public void setBindFlag(String bindFlag) {
        this.bindFlag = bindFlag;
    }

    public String getBindFlag() {
        return bindFlag;
    }

    public void setBindDate(Date bindDate) {
        this.bindDate = bindDate;
    }

    public Date getBindDate() {
        return bindDate;
    }

    public void setDelFlag(String delFlag) {
        this.delFlag = delFlag;
    }

    public String getDelFlag() {
        return delFlag;
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
                .append("id", getId())
                .append("userId", getUserId())
                .append("thirdUniqueAccount", getThirdUniqueAccount())
                .append("thirdUniqueName", getThirdUniqueName())
                .append("thirdUniqueAvatar", getThirdUniqueAvatar())
                .append("bindType", getBindType())
                .append("bindFlag", getBindFlag())
                .append("bindDate", getBindDate())
                .append("createBy", getCreateBy())
                .append("createTime", getCreateTime())
                .append("updateBy", getUpdateBy())
                .append("updateTime", getUpdateTime())
                .append("delFlag", getDelFlag())
                .toString();
    }
}

2.3.2:mapper.java

package com.ruoyi.system.mapper;

import com.ruoyi.system.domain.SysUserThirdAccount;

import java.util.List;

/**
 * @author xiao_he
 */
public interface SysUserThirdAccountMapper {
    /**
     * 查询第三方账户绑定
     *
     * @param id 第三方账户绑定主键
     * @return 第三方账户绑定
     */
    public SysUserThirdAccount selectSysUserThirdAccountById(Long id);

    /**
     * 查询第三方账户绑定列表
     *
     * @param sysUserThirdAccount 第三方账户绑定
     * @return 第三方账户绑定集合
     */
    public List<SysUserThirdAccount> selectSysUserThirdAccountList(SysUserThirdAccount sysUserThirdAccount);

    /**
     * 新增第三方账户绑定
     *
     * @param sysUserThirdAccount 第三方账户绑定
     * @return 结果
     */
    public int insertSysUserThirdAccount(SysUserThirdAccount sysUserThirdAccount);

    /**
     * 修改第三方账户绑定
     *
     * @param sysUserThirdAccount 第三方账户绑定
     * @return 结果
     */
    public int updateSysUserThirdAccount(SysUserThirdAccount sysUserThirdAccount);

    /**
     * 删除第三方账户绑定
     *
     * @param id 第三方账户绑定主键
     * @return 结果
     */
    public int deleteSysUserThirdAccountById(Long id);

    /**
     * 批量删除第三方账户绑定
     *
     * @param ids 需要删除的数据主键集合
     * @return 结果
     */
    public int deleteSysUserThirdAccountByIds(Long[] ids);
}

2.3.3:mapper对应的xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.system.mapper.SysUserThirdAccountMapper">

    <resultMap type="SysUserThirdAccount" id="SysUserThirdAccountResult">
        <result property="id" column="id"/>
        <result property="userId" column="user_id"/>
        <result property="thirdUniqueAccount" column="third_unique_account"/>
        <result property="thirdUniqueName" column="third_unique_name"/>
        <result property="thirdUniqueAvatar" column="third_unique_avatar"/>
        <result property="bindType" column="bind_type"/>
        <result property="bindFlag" column="bind_flag"/>
        <result property="bindDate" column="bind_date"/>
        <result property="createBy" column="create_by"/>
        <result property="createTime" column="create_time"/>
        <result property="updateBy" column="update_by"/>
        <result property="updateTime" column="update_time"/>
        <result property="delFlag" column="del_flag"/>
    </resultMap>

    <sql id="selectSysUserThirdAccountVo">
        select id,
               user_id,
               third_unique_account,
               third_unique_name,
               third_unique_avatar,
               bind_type,
               bind_flag,
               bind_date,
               create_by,
               create_time,
               update_by,
               update_time,
               del_flag
        from sys_user_third_account
    </sql>

    <select id="selectSysUserThirdAccountList" parameterType="SysUserThirdAccount"
            resultMap="SysUserThirdAccountResult">
        <include refid="selectSysUserThirdAccountVo"/>
        <where>
            <if test="userId != null ">and user_id = #{userId}</if>
            <if test="thirdUniqueAccount != null  and thirdUniqueAccount != ''">and third_unique_account =
                #{thirdUniqueAccount}
            </if>
            <if test="thirdUniqueName != null  and thirdUniqueName != ''">and third_unique_name like concat('%',
                #{thirdUniqueName}, '%')
            </if>
            <if test="thirdUniqueAvatar != null  and thirdUniqueAvatar != ''">and third_unique_avatar =
                #{thirdUniqueAvatar}
            </if>
            <if test="bindType != null  and bindType != ''">and bind_type = #{bindType}</if>
            <if test="bindFlag != null  and bindFlag != ''">and bind_flag = #{bindFlag}</if>
            <if test="bindDate != null ">and bind_date = #{bindDate}</if>
            <if test="1==1 "> and del_flag ='0' </if>
        </where>
    </select>

    <select id="selectSysUserThirdAccountById" parameterType="Long" resultMap="SysUserThirdAccountResult">
        <include refid="selectSysUserThirdAccountVo"/>
        where id = #{id}
    </select>

    <insert id="insertSysUserThirdAccount" parameterType="SysUserThirdAccount" useGeneratedKeys="true" keyProperty="id">
        insert into sys_user_third_account
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="userId != null">user_id,</if>
            <if test="thirdUniqueAccount != null">third_unique_account,</if>
            <if test="thirdUniqueName != null">third_unique_name,</if>
            <if test="thirdUniqueAvatar != null">third_unique_avatar,</if>
            <if test="bindType != null">bind_type,</if>
            <if test="bindFlag != null">bind_flag,</if>
            <if test="bindDate != null">bind_date,</if>
            <if test="createBy != null">create_by,</if>
            <if test="createTime != null">create_time,</if>
            <if test="updateBy != null">update_by,</if>
            <if test="updateTime != null">update_time,</if>
            <if test="1==1">del_flag,</if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="userId != null">#{userId},</if>
            <if test="thirdUniqueAccount != null">#{thirdUniqueAccount},</if>
            <if test="thirdUniqueName != null">#{thirdUniqueName},</if>
            <if test="thirdUniqueAvatar != null">#{thirdUniqueAvatar},</if>
            <if test="bindType != null">#{bindType},</if>
            <if test="bindFlag != null">#{bindFlag},</if>
            <if test="bindDate != null">#{bindDate},</if>
            <if test="createBy != null">#{createBy},</if>
            <if test="createTime != null">#{createTime},</if>
            <if test="updateBy != null">#{updateBy},</if>
            <if test="updateTime != null">#{updateTime},</if>
            <if test="1==1">#{delFlag},</if>
        </trim>
    </insert>

    <update id="updateSysUserThirdAccount" parameterType="SysUserThirdAccount">
        update sys_user_third_account
        <trim prefix="SET" suffixOverrides=",">
            <if test="userId != null">user_id = #{userId},</if>
            <if test="thirdUniqueAccount != null">third_unique_account = #{thirdUniqueAccount},</if>
            <if test="thirdUniqueName != null">third_unique_name = #{thirdUniqueName},</if>
            <if test="thirdUniqueAvatar != null">third_unique_avatar = #{thirdUniqueAvatar},</if>
            <if test="bindType != null">bind_type = #{bindType},</if>
            <if test="bindFlag != null">bind_flag = #{bindFlag},</if>
            <if test="bindDate != null">bind_date = #{bindDate},</if>
            <if test="createBy != null">create_by = #{createBy},</if>
            <if test="createTime != null">create_time = #{createTime},</if>
            <if test="updateBy != null">update_by = #{updateBy},</if>
            <if test="updateTime != null">update_time = #{updateTime},</if>
            <if test="delFlag != null">del_flag = #{delFlag},</if>
        </trim>
        where id = #{id}
    </update>

    <delete id="deleteSysUserThirdAccountById" parameterType="Long">
        update sys_user_third_account
        set del_flag = '2'
        where id = #{id}
    </delete>

    <delete id="deleteSysUserThirdAccountByIds" parameterType="String">
        update sys_user_third_account set del_flag = '2' where id in
        <foreach item="id" collection="array" open="(" separator="," close=")">
            #{id}
        </foreach>
    </delete>
</mapper>

2.3.4:service接口

package com.ruoyi.system.service;

import com.ruoyi.system.domain.SysUserThirdAccount;

import java.util.List;

/**
 * @author xiao_he
 */
public interface ISysUserThirdAccountService {
    /**
     * 查询第三方账户绑定
     *
     * @param id 第三方账户绑定主键
     * @return 第三方账户绑定
     */
    public SysUserThirdAccount selectSysUserThirdAccountById(Long id);

    /**
     * 查询第三方账户绑定列表
     *
     * @param sysUserThirdAccount 第三方账户绑定
     * @return 第三方账户绑定集合
     */
    public List<SysUserThirdAccount> selectSysUserThirdAccountList(SysUserThirdAccount sysUserThirdAccount);

    /**
     * 新增第三方账户绑定
     *
     * @param sysUserThirdAccount 第三方账户绑定
     * @return 结果
     */
    public int insertSysUserThirdAccount(SysUserThirdAccount sysUserThirdAccount);

    /**
     * 修改第三方账户绑定
     *
     * @param sysUserThirdAccount 第三方账户绑定
     * @return 结果
     */
    public int updateSysUserThirdAccount(SysUserThirdAccount sysUserThirdAccount);

    /**
     * 批量删除第三方账户绑定
     *
     * @param ids 需要删除的第三方账户绑定主键集合
     * @return 结果
     */
    public int deleteSysUserThirdAccountByIds(Long[] ids);

    /**
     * 删除第三方账户绑定信息
     *
     * @param id 第三方账户绑定主键
     * @return 结果
     */
    public int deleteSysUserThirdAccountById(Long id);
}

2.3.5:service实现类

package com.ruoyi.system.service.impl;

import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.system.domain.SysUserThirdAccount;
import com.ruoyi.system.mapper.SysUserThirdAccountMapper;
import com.ruoyi.system.service.ISysUserThirdAccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @author xiao_he
 */
@Service("sysUserThirdAccountService")
public class SysUserThirdAccountServiceImpl implements ISysUserThirdAccountService {
    @Autowired
    private SysUserThirdAccountMapper sysUserThirdAccountMapper;

    /**
     * 查询第三方账户绑定
     *
     * @param id 第三方账户绑定主键
     * @return 第三方账户绑定
     */
    @Override
    public SysUserThirdAccount selectSysUserThirdAccountById(Long id) {
        return sysUserThirdAccountMapper.selectSysUserThirdAccountById(id);
    }

    /**
     * 查询第三方账户绑定列表
     *
     * @param sysUserThirdAccount 第三方账户绑定
     * @return 第三方账户绑定
     */
    @Override
    public List<SysUserThirdAccount> selectSysUserThirdAccountList(SysUserThirdAccount sysUserThirdAccount) {
        return sysUserThirdAccountMapper.selectSysUserThirdAccountList(sysUserThirdAccount);
    }

    /**
     * 新增第三方账户绑定
     *
     * @param sysUserThirdAccount 第三方账户绑定
     * @return 结果
     */
    @Override
    public int insertSysUserThirdAccount(SysUserThirdAccount sysUserThirdAccount) {
        sysUserThirdAccount.setCreateTime(DateUtils.getNowDate());
        return sysUserThirdAccountMapper.insertSysUserThirdAccount(sysUserThirdAccount);
    }

    /**
     * 修改第三方账户绑定
     *
     * @param sysUserThirdAccount 第三方账户绑定
     * @return 结果
     */
    @Override
    public int updateSysUserThirdAccount(SysUserThirdAccount sysUserThirdAccount) {
        sysUserThirdAccount.setUpdateTime(DateUtils.getNowDate());
        return sysUserThirdAccountMapper.updateSysUserThirdAccount(sysUserThirdAccount);
    }

    /**
     * 批量删除第三方账户绑定
     *
     * @param ids 需要删除的第三方账户绑定主键
     * @return 结果
     */
    @Override
    public int deleteSysUserThirdAccountByIds(Long[] ids) {
        return sysUserThirdAccountMapper.deleteSysUserThirdAccountByIds(ids);
    }

    /**
     * 删除第三方账户绑定信息
     *
     * @param id 第三方账户绑定主键
     * @return 结果
     */
    @Override
    public int deleteSysUserThirdAccountById(Long id) {
        return sysUserThirdAccountMapper.deleteSysUserThirdAccountById(id);
    }
}

2.3.5:SysUserThirdAccountController

package cn.hfm.web.controller.system;

import java.util.List;
import javax.servlet.http.HttpServletResponse;

import cn.hfm.common.utils.SecurityUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import cn.hfm.common.annotation.Log;
import cn.hfm.common.core.controller.BaseController;
import cn.hfm.common.core.domain.AjaxResult;
import cn.hfm.common.enums.BusinessType;
import cn.hfm.system.domain.SysUserThirdAccount;
import cn.hfm.system.service.ISysUserThirdAccountService;
import cn.hfm.common.utils.poi.ExcelUtil;
import cn.hfm.common.core.page.TableDataInfo;

/**
 * 第三方账户绑定Controller
 *
 * @author xiao_he
 * @date 2023-07-07
 */
@RestController
@RequestMapping("/system/account")
public class SysUserThirdAccountController extends BaseController {
    @Autowired
    private ISysUserThirdAccountService sysUserThirdAccountService;

    /**
     * 查询第三方账户绑定列表
     */
    @PreAuthorize("@ss.hasPermi('system:account:list')")
    @GetMapping("/list")
    public TableDataInfo list(SysUserThirdAccount sysUserThirdAccount) {
        startPage();
        List<SysUserThirdAccount> list = sysUserThirdAccountService.selectSysUserThirdAccountList(sysUserThirdAccount);
        return getDataTable(list);
    }

    /**
     * 导出第三方账户绑定列表
     */
    @PreAuthorize("@ss.hasPermi('system:account:export')")
    @Log(title = "第三方账户绑定", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, SysUserThirdAccount sysUserThirdAccount) {
        List<SysUserThirdAccount> list = sysUserThirdAccountService.selectSysUserThirdAccountList(sysUserThirdAccount);
        ExcelUtil<SysUserThirdAccount> util = new ExcelUtil<SysUserThirdAccount>(SysUserThirdAccount.class);
        util.exportExcel(response, list, "第三方账户绑定数据");
    }

    /**
     * 获取第三方账户绑定详细信息
     */
    @PreAuthorize("@ss.hasPermi('system:account:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        return AjaxResult.success(sysUserThirdAccountService.selectSysUserThirdAccountById(id));
    }

    /**
     * 新增第三方账户绑定
     */
    @PreAuthorize("@ss.hasPermi('system:account:add')")
    @Log(title = "第三方账户绑定", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody SysUserThirdAccount sysUserThirdAccount) {
        return toAjax(sysUserThirdAccountService.insertSysUserThirdAccount(sysUserThirdAccount));
    }

    /**
     * 修改第三方账户绑定
     */
    @PreAuthorize("@ss.hasPermi('system:account:edit')")
    @Log(title = "第三方账户绑定", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody SysUserThirdAccount sysUserThirdAccount) {
        return toAjax(sysUserThirdAccountService.updateSysUserThirdAccount(sysUserThirdAccount));
    }

    /**
     * 删除第三方账户绑定
     */
    @PreAuthorize("@ss.hasPermi('system:account:remove')")
    @Log(title = "第三方账户绑定", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable Long[] ids) {
        return toAjax(sysUserThirdAccountService.deleteSysUserThirdAccountByIds(ids));
    }


    /**
     * 查询当前用户第三方账户绑定列表
     */
    @GetMapping("/thirdAccountList")
    public TableDataInfo thirdAccountList(SysUserThirdAccount sysUserThirdAccount) {
        //设置优化id
        sysUserThirdAccount.setUserId(SecurityUtils.getUserId());
        sysUserThirdAccount.setBindFlag("1");
        startPage();
        List<SysUserThirdAccount> list = sysUserThirdAccountService.selectSysUserThirdAccountList(sysUserThirdAccount);
        return getDataTable(list);
    }
}

第三步:若依的登录鉴权使用了springSecurity,现在我们对它进行基本的配置

3.1:创建OtherAuthenticationToken继承AbstractAuthenticationToken,里面的代码照抄就行了

package com.ruoyi.framework.security.othreLogin;

import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;

import java.util.Collection;

/**
 * @author xiao_he
 */
public class OtherAuthenticationToken extends AbstractAuthenticationToken {
    private final Object principal;

    public OtherAuthenticationToken(Object principal) {
        super(null);
        this.principal = principal;
        this.setAuthenticated(false);
    }

    public OtherAuthenticationToken(Object principal, Collection<? extends GrantedAuthority> authorities) {
        super(authorities);
        this.principal = principal;
        super.setAuthenticated(true);
    }

    @Override
    public Object getCredentials() {
        return null;
    }

    @Override
    public Object getPrincipal() {
        return this.principal;
    }

    @Override
    public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
        if (isAuthenticated) {
            throw new IllegalArgumentException(
                    "Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");
        }

        super.setAuthenticated(false);
    }

    @Override
    public void eraseCredentials() {
        super.eraseCredentials();
    }
}

3.2:创建OtherAuthenticationProvider实现AuthenticationProvider,这里的UserDetailsService在后面定义

package com.ruoyi.framework.security.othreLogin;

import com.ruoyi.framework.web.service.UserDetailsByOtherLoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;

import java.util.Collections;

/**
 * @author xiao_he
 */
@Component
public class OtherAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    @Qualifier("userDetailsByOtherLoginService")
    private UserDetailsService userDetailsByOtherLoginService;

    /**
     * 认证逻辑
     */
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        OtherAuthenticationToken otherAuthenticationToken = (OtherAuthenticationToken) authentication;
        String thirdUniqueAccountId = (String) otherAuthenticationToken.getPrincipal();
        UserDetails user = userDetailsByOtherLoginService.loadUserByUsername(thirdUniqueAccountId);
        OtherAuthenticationToken result = new OtherAuthenticationToken(user, Collections.emptyList());
        /*
        Details 中包含了 ip地址、 sessionId 等等属性 也可以存储一些自己想要放进去的内容
        */
        result.setDetails(otherAuthenticationToken.getDetails());
        return result;
    }

    /**
     * UserIdAuthenticationToken交给UserIdAuthenticationProvider处理
     *
     * @param aClass
     * @return
     */
    @Override
    public boolean supports(Class<?> aClass) {
        return OtherAuthenticationToken.class.isAssignableFrom(aClass);
    }
}

3.3:创建一个工具类,用来获取第三方token、获取用户信息

package com.ruoyi.framework.security.othreLogin;

import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.enums.UserStatus;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.framework.web.service.SysPermissionService;
import com.ruoyi.system.domain.SysUserThirdAccount;
import com.ruoyi.system.service.ISysUserThirdAccountService;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.userdetails.UserDetails;

import java.io.IOException;
import java.util.Date;
import java.util.List;


/**
 * @author xiao_he
 */
public class UserDetailsUtils {
    private static final Logger log = LoggerFactory.getLogger(UserDetailsUtils.class);

    public static UserDetails createLoginUser(SysUser user) {
        SysPermissionService permissionService = SpringUtils.getBean("sysPermissionService");
        if (StringUtils.isNull(user)) {
            log.info("该用户未绑定账户,请先进行注册后绑定!");
            throw new ServiceException("该用户未绑定账户,请先进行注册后绑定!");
        } else if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) {
            log.info("登录用户:{} 已被删除.", user.getUserName());
            throw new ServiceException("对不起,您的账号:" + user.getUserName() + " 已被删除");
        } else if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
            log.info("登录用户:{} 已被停用.", user.getUserName());
            throw new ServiceException("对不起,您的账号:" + user.getUserName() + " 已停用");
        }
        return new LoginUser(user.getUserId(), user.getDeptId(), user, permissionService.getMenuPermission(user));
    }

    public static void bindOtherUser(String token, String loginType, SysUser sysUser) throws IOException {
        if (StringUtils.isNotEmpty(token) && StringUtils.isNotEmpty(loginType)) {
            JSONObject jsonObject = getUserInfo(token, loginType);
            Object otherId = jsonObject.get("id");
            SysUserThirdAccount sysUserThirdAccount = new SysUserThirdAccount();
            sysUserThirdAccount.setBindType(loginType);
            sysUserThirdAccount.setThirdUniqueName(jsonObject.getString("name"));
            sysUserThirdAccount.setThirdUniqueAvatar(jsonObject.getString("avatar_url"));
            sysUserThirdAccount.setDelFlag("0");
            sysUserThirdAccount.setBindFlag("1");
            sysUserThirdAccount.setBindDate(new Date());
            sysUserThirdAccount.setThirdUniqueAccount(otherId.toString());
            ISysUserThirdAccountService userThirdAccountService = SpringUtils.getBean("sysUserThirdAccountService");
            List<SysUserThirdAccount> sysUserThirdAccounts = userThirdAccountService.selectSysUserThirdAccountList(sysUserThirdAccount);
            if (sysUserThirdAccounts.size() < 1) {
                sysUserThirdAccount.setUserId(sysUser.getUserId());
                userThirdAccountService.insertSysUserThirdAccount(sysUserThirdAccount);
            }
        }

    }
    /**
     * 获取Access Token
     *
     * @param url
     * @param loginType 用来拓展以后还有其他的登录逻辑处理
     * @return
     * @throws IOException
     */
    public static JSONObject getAccessToken(String url, String loginType) {
        HttpClient client = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(url);
        httpPost.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36");
        HttpResponse response = null;
        try {
            response = client.execute(httpPost);
            HttpEntity entity = response.getEntity();
            if (null != entity) {
                String result = EntityUtils.toString(entity, "UTF-8");
                return JSONObject.parseObject(result);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            httpPost.releaseConnection();
        }
        return null;
    }

    /**
     * 获取用户信息
     *
     * @param tokenId
     * @param loginType 用来拓展以后还有其他的登录逻辑处理,
     * @return
     */
    public static JSONObject getUserInfo(String tokenId, String loginType) {
        String url = "https://gitee.com/api/v5/user?access_token=" + tokenId;
        CloseableHttpClient client = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet(url);
        httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36");
        HttpResponse response = null;
        try {
            response = client.execute(httpGet);
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                String result = EntityUtils.toString(entity, "UTF-8");
                return JSONObject.parseObject(result);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            httpGet.releaseConnection();
        }
        return null;
    }
}

3.4:Constants常量类中添加几个常量


/**
 * REDIRECT 重定向地址
 */
public static final String REDIRECT = "redirect";

/**
 * AUTH_METHOD 授权类型
 */
public static final String AUTH_METHOD = "authMethod";
/**
 * AUTH_METHOD_KEY 登录方式 redisKey
 */
public static final String AUTH_METHOD_KEY = "authMethod:";


/**
 * LOGIN_TYPE 登录方式
 */
public static final String LOGIN_TYPE = "loginType";


public static final String OTHER_ID = "otherId";

3.5:LoginBody类中添加字段,并提供get/set方法

/**
 * 第三方token
 */
private String token;

/**
 * 登录类型
 */
private String loginType;

3.6:创建UserDetailsByOtherLoginService实现UserDetailsService做第三方登录处理逻辑

package com.ruoyi.framework.web.service;

import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.framework.security.othreLogin.UserDetailsUtils;
import com.ruoyi.system.domain.SysUserThirdAccount;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.system.service.ISysUserThirdAccountService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
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 xiao_he
 */
@Service("userDetailsByOtherLoginService")
public class UserDetailsByOtherLoginService implements UserDetailsService {
    @Autowired
    private ISysUserService userService;


    @Autowired
    private ISysUserThirdAccountService userThirdAccountService;

    @Override
    public UserDetails loadUserByUsername(String tokenId) throws UsernameNotFoundException {
        JSONObject jsonObject = null;
        //在session里拿loginType
        String loginType = (String) ServletUtils.getRequest().getSession().getAttribute(Constants.LOGIN_TYPE);
        jsonObject = UserDetailsUtils.getUserInfo(tokenId, loginType);
        Object thirdUniqueAccountId = jsonObject.get("id");
        SysUserThirdAccount sysUserThirdAccount = new SysUserThirdAccount();
        sysUserThirdAccount.setBindType(loginType);
        sysUserThirdAccount.setDelFlag("0");
        sysUserThirdAccount.setBindFlag("1");
        sysUserThirdAccount.setThirdUniqueAccount(thirdUniqueAccountId.toString());
        List<SysUserThirdAccount> sysUserThirdAccounts = userThirdAccountService.selectSysUserThirdAccountList(sysUserThirdAccount);
        Long userId = 0L;
        if (sysUserThirdAccounts.size() > 0) {
            userId = sysUserThirdAccounts.get(0).getUserId();
        } else {
            SysUser user = new SysUser();
            user.setUserId(-1L);
            ServletUtils.getRequest().setAttribute(Constants.OTHER_ID, thirdUniqueAccountId);
            //没有绑定用户,伪造一个用户,防止报错
            return new LoginUser(-1L, null, user, null);
        }
        SysUser user = userService.selectUserById(userId);
        UserDetails loginUser = UserDetailsUtils.createLoginUser(user);
        return loginUser;
    }
}

3.7:在原来UserDetailsServiceImpl上添加注解,区分是哪个处理逻辑

@Service("userDetailsByPasswordService")

3.8:配置SecurityConfig

3.8.1:在原来的注入UserDetailsService类上添加注解指定userDetailsByPasswordService

/**
 * 自定义用户认证逻辑
 */
@Autowired
@Qualifier("userDetailsByPasswordService")
private UserDetailsService userDetailsService;

3.8.2:添加认证白名单,这几个链接配置为免登录链接

.antMatchers("/otherLogin", "/preOtherAuthUrl", "/otherLoginCallback/**","/system/dict/data/type/**").permitAll()

3.8.3:将AuthenticationGiteeProvider注入进来,配置configure方法,添加一行auth.authenticationProvider(authenticationGiteeProvider);

@Autowired
private AuthenticationGiteeProvider authenticationGiteeProvider;

/**
 * 身份认证接口
 */
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
    auth.authenticationProvider(authenticationGiteeProvider);
}

3.8.4:SysLoginService中添加登录方法和绑定方法

/**
 * 登录验证
 *
 * @param token     登录验证token
 * @param loginType 登录类型,后期拓展
 * @return 结果
 */
public String otherLogin(String token, String loginType) {
    // 用户验证
    Authentication authentication = null;
    try {
        // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
        if ("1".equals(loginType) || "2".equals(loginType) || "3".equals(loginType)) {
            authentication = authenticationManager.authenticate(new OtherAuthenticationToken(token));
        }
    } catch (Exception e) {
        if (e instanceof BadCredentialsException) {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor("username", Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
            throw new UserPasswordNotMatchException();
        } else {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor("username", Constants.LOGIN_FAIL, e.getMessage()));
            throw new ServiceException(e.getMessage());
        }
    }
    AsyncManager.me().execute(AsyncFactory.recordLogininfor(authentication.getName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
    LoginUser loginUser = (LoginUser) authentication.getPrincipal();
    recordLoginInfo(loginUser.getUserId());
    // 生成token
    return tokenService.createToken(loginUser);
}

/**
 * 绑定第三方账户
 *
 * @param tokenId   第三放认证后的token
 * @param loginType 登录类型
 */
public void bindThirdAccount(String tokenId, String loginType) {
    LoginUser loginUser = SecurityUtils.getLoginUser();
    SysUser sysUser = loginUser.getUser();
    JSONObject jsonObject = null;
    jsonObject = UserDetailsUtils.getUserInfo(tokenId, loginType);
    SysUserThirdAccount thirdAccount = new SysUserThirdAccount();
    thirdAccount.setBindType(loginType);
    thirdAccount.setDelFlag("0");
    thirdAccount.setBindFlag("1");
    thirdAccount.setThirdUniqueAccount(jsonObject.getString("id"));
    List<SysUserThirdAccount> sysUserThirdAccounts = userThirdAccountService.selectSysUserThirdAccountList(thirdAccount);
    if (sysUserThirdAccounts.size() > 0) {
        //绑定过账户
        SysUserThirdAccount userThirdAccount = sysUserThirdAccounts.get(0);
        if (!userThirdAccount.equals(SecurityUtils.getUserId())) {
            throw new ServiceException("该合作账户已经绑定过其他账户,请先解绑其他账户!");
        }
        userThirdAccount.setThirdUniqueName(jsonObject.getString("name"));
        userThirdAccount.setThirdUniqueAvatar(jsonObject.getString("avatar_url"));
        userThirdAccount.setBindFlag("1");
        userThirdAccount.setBindDate(new Date());
        userThirdAccount.setUserId(SecurityUtils.getUserId());
        userThirdAccountService.updateSysUserThirdAccount(userThirdAccount);
    } else {
        //看看当前账户有没有已经解绑的同类型,并且同tokenId账户,有解绑的了的,覆盖掉
        thirdAccount.setBindFlag("2");
        sysUserThirdAccounts = userThirdAccountService.selectSysUserThirdAccountList(thirdAccount);
        //设置绑定时间,以及第三方账号id
        thirdAccount.setThirdUniqueName(jsonObject.getString("name"));
        thirdAccount.setThirdUniqueAvatar(jsonObject.getString("avatar_url"));
        thirdAccount.setBindDate(new Date());
        thirdAccount.setBindFlag("1");
        thirdAccount.setUserId(SecurityUtils.getUserId());
        thirdAccount.setThirdUniqueAccount(jsonObject.getString("id"));
        if (sysUserThirdAccounts.size() > 0) {
            thirdAccount.setId(sysUserThirdAccounts.get(0).getId());
            userThirdAccountService.updateSysUserThirdAccount(thirdAccount);
        } else {
            userThirdAccountService.insertSysUserThirdAccount(thirdAccount);
        }
    }
}

3.8.5:创建OtherLoginController

package com.ruoyi.web.controller.system;

import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.model.LoginBody;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.uuid.UUID;
import com.ruoyi.framework.security.othreLogin.UserDetailsUtils;
import com.ruoyi.framework.web.service.SysLoginService;
import com.ruoyi.system.domain.SysUserThirdAccount;
import com.ruoyi.system.service.ISysUserThirdAccountService;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;


/**
 * @author xiao_he
 */
@RestController
public class OtherLoginController {
    @Autowired
    private SysLoginService loginService;

    @Autowired
    private ISysUserThirdAccountService userThirdAccountService;

    @Autowired
    private RedisCache redisCache;

    /**
     * gitee授权中提供的 appid 和 appkey
     */
    @Value("${otherLogin.gitee.clientid}")
    public String  GIT_EE_CLIENT_ID;
    @Value("${otherLogin.gitee.clientsecret}")
    public String GIT_EE_CLIENT_SECRET;
    @Value("${otherLogin.gitee.callback}")
    public String GIT_EE_CLIENT_URL;
    @Value("${ruoyi.doMain}")
    public String DO_MAIN;


    /**
     * 其他合作账户登录的公共方法
     *
     * @param loginBody
     * @param request
     * @return
     */
    @PostMapping("/otherLogin")
    public AjaxResult otherLogin(@RequestBody LoginBody loginBody, HttpServletRequest request) {
        AjaxResult ajax = AjaxResult.success();
        String redirect = String.valueOf(request.getSession().getAttribute(Constants.REDIRECT));
        //授权类型
        String method = (String) redisCache.getCacheObject(Constants.AUTH_METHOD_KEY + loginBody.getUuid());
        request.getSession().setAttribute(Constants.LOGIN_TYPE, loginBody.getLoginType());
        if ("login".equals(method)) {
            //验证token
            String token = loginService.otherLogin(loginBody.getToken(), loginBody.getLoginType());
            Object otherID = ServletUtils.getRequest().getAttribute(Constants.OTHER_ID);
            if (ObjectUtils.isEmpty(otherID)) {
                ajax.put(Constants.OTHER_ID, null);
                ajax.put(Constants.TOKEN, token);
                ajax.put(Constants.AUTH_METHOD, method);
                if (StringUtils.isNotEmpty(redirect) && (!"undefined".equals(redirect)) && (!"null".equals(redirect))) {
                    ajax.put(Constants.REDIRECT, redirect);
                } else {
                    ajax.put(Constants.REDIRECT, null);
                }
            } else {
                //么有token
                ajax.put(Constants.TOKEN, null);
                ajax.put(Constants.OTHER_ID, otherID);
            }
        } else {
            //这是绑定账户走的
            loginService.bindThirdAccount(loginBody.getToken(), loginBody.getLoginType());
            ajax.put(Constants.AUTH_METHOD, method);
        }
        return ajax;
    }


    /**
     * 解绑第三方账户
     */
    @Log(title = "解绑第三方账户", businessType = BusinessType.UPDATE)
    @PostMapping("/unBindThirdAccount")
    public AjaxResult unBindThirdAccount(@RequestBody SysUserThirdAccount userThirdAccount) throws IOException {
        userThirdAccount.setUserId(SecurityUtils.getUserId());
        //查询当前账号的绑定账号
        userThirdAccount.setBindFlag("1");
        List<SysUserThirdAccount> sysUserThirdAccounts = userThirdAccountService.selectSysUserThirdAccountList(userThirdAccount);
        if (sysUserThirdAccounts.size() > 0) {
            SysUserThirdAccount sysUserThirdAccount = sysUserThirdAccounts.get(0);
            //解绑账号
            sysUserThirdAccount.setBindFlag("2");
            userThirdAccountService.updateSysUserThirdAccount(sysUserThirdAccount);
            return AjaxResult.success();
        }
        return AjaxResult.error("未找到绑定账号!");
    }


    /**
     * 获取第三方登录认证url
     *
     * @param request
     * @return
     */
    @GetMapping("/preOtherAuthUrl")
    public AjaxResult preOtherAuthUrl(HttpServletRequest request) {
        AjaxResult ajax = AjaxResult.success();
        HttpSession session = request.getSession();
        // 用于第三方应用防止CSRF攻击
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        session.setAttribute("state", uuid);
        String redirect = request.getParameter(Constants.REDIRECT);
        if (StringUtils.isNotEmpty(redirect)) {
            session.setAttribute(Constants.REDIRECT, redirect);
        }
        //授权类型
        redisCache.setCacheObject(Constants.AUTH_METHOD_KEY + uuid, request.getParameter(Constants.AUTH_METHOD), Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
        // Step1:获取Authorization Code
        String authorizeUrl = "https://gitee.com/oauth/authorize?response_type=code" +
                "&client_id=" + GIT_EE_CLIENT_ID +
                "&redirect_uri=" + GIT_EE_CLIENT_URL +
                "&state=" + uuid +
                "&scope=user_info";
        //存储
        ajax.put("authorizeUrl", authorizeUrl);
        ajax.put("uuid", uuid);
        return ajax;
    }


    /**
     *  授权后的回调方法
     * @param loginType 第三方登录类型
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @GetMapping("/otherLoginCallback/{loginType}")
    public AjaxResult otherLoginCallback(@PathVariable("loginType") String loginType, HttpServletRequest request, HttpServletResponse response) throws IOException {
        HttpSession session = request.getSession();
        // 得到Authorization Code
        String code = request.getParameter("code");
        // 我们放在地址中的状态码
        String state = request.getParameter("state");
        String uuid = (String) session.getAttribute("state");
        //类型
        String method = (String) redisCache.getCacheObject(Constants.AUTH_METHOD_KEY + uuid);
        // 验证信息我们发送的状态码
        if (null != uuid) {
            // 状态码不正确,直接返回登录页面
            if (!uuid.equals(state)) {
                return AjaxResult.error();
            }
        }
        // Step1:获取Authorization Code
        String authorizeUrl = "https://gitee.com/oauth/token?grant_type=authorization_code" +
                "&client_id=" + GIT_EE_CLIENT_ID +
                "&client_secret=" + GIT_EE_CLIENT_SECRET +
                "&code=" + code +
                "&redirect_uri=" + GIT_EE_CLIENT_URL;
        // Step2:通过Authorization Code获取Access Token
        String redirect = "";
        JSONObject accessTokenJson = UserDetailsUtils.getAccessToken(authorizeUrl,loginType);
        Object redirectPath = session.getAttribute(Constants.REDIRECT);
        if ("login".equals(method)) {
            if (redirectPath != null) {
                redirect = DO_MAIN + "/cmsLogin?redirect=" + redirectPath + "&callback_token=" + accessTokenJson.get("access_token") + "&callback_login_type=" + loginType + "&callback_uuid=" + uuid;
            } else {
                redirect = DO_MAIN + "/cmsLogin" + "?callback_token=" + accessTokenJson.get("access_token") + "&callback_login_type=" + loginType + "&callback_uuid=" + uuid;
            }
        } else {
            redirect = DO_MAIN + "/user/profile?callback_token=" + accessTokenJson.get("access_token") + "&callback_login_type=" + loginType + "&callback_uuid=" + uuid;
        }
        response.sendRedirect(redirect);
        return AjaxResult.success();
    }
}

第四步:开始编写前端代码

4.1:在login.js添加方法

//第三方登录获取url
export function preOtherAuthUrl(redirect, authMethod, loginType) {
  return request({
    url: '/preOtherAuthUrl',
    headers: {
      isToken: false
    },
    params: {
      'redirect': redirect,
      'authMethod': authMethod,
      'loginType': loginType
    },
    method: 'get',
  })
}

export function otherLogin(token, loginType, uuid) {
  const data = {
    token,
    loginType,
    uuid
  }
  return request({
    url: '/otherLogin',
    method: 'post',
    data: data
  })
}

// 修改用户个人信息
export function unBindThirdAccount(data) {
  return request({
    url: '/unBindThirdAccount',
    method: 'post',
    data: data
  })
}

4.2:ruoyi-ui/src/store/modules/user.js添加方法

otherLogin({commit}, body) {
  return new Promise((resolve, reject) => {
    otherLogin(body.token, body.loginType, body.uuid).then(res => {
      let token = res.token;
      if ('login' == res.authMethod && null != token) {
        //如果是登录请求,需要重新设置token
        setToken(res.token)
        commit('SET_TOKEN', res.token)
      }
      resolve(res)
    }).catch(error => {
      reject(error)
    })
  })
},

3.8.6:需要加入的字典数据,这里后面会用到

INSERT INTO `sys_dict_type` VALUES (104,'第三方用户状态','user_third_status','0','plat','2023-07-07 11:23:04','',NULL,NULL);
INSERT INTO `sys_dict_data` VALUES (108,0,'已绑定','1','user_third_status',NULL,'success','N','0','plat','2023-07-07 11:24:00','',NULL,NULL);
INSERT INTO `sys_dict_data` VALUES (109,1,'未绑定','0','user_third_status',NULL,'danger','N','0','plat','2023-07-07 11:24:37','plat','2023-07-07 11:25:08',NULL);
INSERT INTO `sys_dict_data` VALUES (110,2,'已解绑','2','user_third_status',NULL,'danger','N','0','plat','2023-07-07 11:24:57','',NULL,NULL);

INSERT INTO `sys_dict_type` VALUES (103,'合作平台','third_account_type','0','plat','2023-07-07 11:23:04','plat','2023-10-13 01:27:12','第三方数据登录平台');
INSERT INTO `sys_dict_data` VALUES (106,0,'gitee','1','third_account_type',NULL,'','N','0','plat','2023-07-07 11:24:00','',NULL,NULL);

4.3:前端模块代码

4.3.1:添加一个gitee的图标,在项目路径src/assets/icons/svg/下新建gitee.svg文件,内容把这些复制进去

<svg height="32" viewBox="0 0 32 32" width="32" xmlns="http://www.w3.org/2000/svg">
  <g fill="none" fill-rule="evenodd">
    <circle cx="16" cy="16" fill="#c71d23" r="16"/>
    <path
      d="m24.0987698 14.2225144h-9.0863697c-.4362899.000207-.7900048.3538292-.790326.7901191l-.0005173 1.9752185c-.0003277.4363707.353328.7902117.7896987.790326.0000712 0 .0001424 0 .0002135-.0002135l5.5317648-.0000461c.4363708-.0000102.7901221.3537352.7901257.790106 0 .0000022 0 .0000044-.0000066.0000066v.1975077.1975318c0 1.3091122-1.0612451 2.3703573-2.3703573 2.3703573h-7.5067195c-.4363081-.0000218-.790009-.353713-.7900429-.7900211l-.0002069-7.5059917c-.0001014-1.3091122 1.0611145-2.3703865 2.3702267-2.3704226.0000217 0 .0000435 0 .0000653.0000653h11.0602463c.4361793-.0004902.7898484-.35394.7906091-.79011894l.0012251-1.97521881c.0007606-.43637034-.3527683-.79033806-.7891389-.79060871-.0001634-.0000001-.0003268-.00000015-.0004901.00048976h-11.0617654c-3.27278051 0-5.92589329 2.65311278-5.92589329 5.9258933v11.0612755c0 .4363707.35374837.7901191.7901191.7901191h11.65447149c2.9454379 0 5.3331872-2.3877493 5.3331872-5.3331872v-4.5430682c0-.4363707-.3537484-.7901191-.7901191-.7901191z"
      fill="#fff"/>
  </g>
</svg>

4.3.2:添加字典,写在script下,这个是用来获取字典数据的

dicts: ['third_account_type'],

若依 第三方登录,java

4.3.3:添加按钮

<el-form-item>
  <el-divider content-position="center" ><span style="color: #606266 !important;">其他方式登录</span></el-divider>
  <div class="loginMethods">
    <div class="loginMethod" v-for="(item,index) in dict.type['third_account_type']" :key="index +'qrqwr'"
         @click="otherLogin(item)"
    >
      <svg-icon :icon-class="item.label"/>
    </div>
  </div>
</el-form-item>

4.3.4:添加样式,这个随意,你们可以自己调整

.loginMethods {
  display: flex;
  justify-content: center;
  align-content: center;
  gap: 20px;

  .loginMethod {
    cursor: pointer;
    font-size: 35px;
  }
}

4.3.5:添加登录方法

otherLogin(item) {
  let that = this
  this.$modal.loading('正在登录中,请稍后')
  preOtherAuthUrl(that.redirect, 'login', item).then(res => {
    window.location = res.authorizeUrl
  })
},

4.3.6:添加生命周期函数

mounted() {
  let token = this.$route.query.callback_token
  let loginType = this.$route.query.callback_login_type
  let uuid = this.$route.query.callback_uuid
  if (token == 'null') {
    this.$modal.msgWarning('用户取消授权')
  } else if (token != undefined && token != null && token != '' && token != 'null' && loginType != undefined && loginType != null && loginType != '') {
    const formBody = {
      token: token,
      loginType: loginType,
      uuid: uuid
    }
    this.$modal.loading('正在登录中,请稍后')
    this.$store.dispatch('otherLogin', formBody).then((res) => {
        this.$router.push({path: res.redirect || '/cms/main/cmsIndex'}).catch(() => {
        })
    }).catch((res) => {
    }).finally(res => {
      this.$modal.closeLoading()
    })
  }
}

第五步:绑定页面设计

若依 第三方登录,java

5.1:第三方绑定组件,我把这个单独抽出了一个组件处理

<template>
  <div style="display: flex;gap: 20px;flex-wrap: wrap">
    <el-card style="width: 100%;">
      <div slot="header" class="clearfix">
        <span>第三方账户绑定</span>
      </div>
      <el-table :data="tableData" border>
        <el-table-column
          type="index" align="center"
          label="序号"
          width="50">
        </el-table-column>
        <el-table-column
          align="center"
          label="帐号信息"
          width="100">
          <template slot-scope="scope">
            <svg-icon style="font-size: 35px" :icon-class="getLogoUrl(scope.row.bindType)"/>
          </template>
        </el-table-column>
        <el-table-column
          prop="date"
          label="详情"
          align="center"
          width="180">
          <template slot-scope="scope">
            <div style="display: flex;justify-content: center;align-items: center;gap: 10px">
              <img class="otherLogo" :src="scope.row.thirdUniqueAvatar">
              <span class="demonstration">{{ scope.row.thirdUniqueName }}</span>
            </div>
          </template>
        </el-table-column>
        <el-table-column
          prop="bindDate"
          min-width="120"
          align="center"
          label="绑定时间">
        </el-table-column>
        <el-table-column
          align="center"
          label="状态">
          <template slot-scope="scope">
            <dict-tag :options="dict.type['user_third_status']" :value="scope.row.bindFlag"></dict-tag>
          </template>
        </el-table-column>
        <el-table-column
          align="center"
          label="操作"
          width="100">
          <template slot-scope="scope">
            <el-button v-if="scope.row.bindFlag ==1" @click="unbind(scope.row)" type="text" size="small">取消绑定
            </el-button>
          </template>
        </el-table-column>
      </el-table>
    </el-card>
    <el-card style="width: 100%;">
      <div slot="header" class="clearfix">
        <span>你可以绑定以下第三方帐号用于登录</span>
      </div>
      <div class="loginMethods">
        <div class="loginMethod" v-for="(item,index) in dict.type['third_account_type']" v-if="item.show"
             :key="index +'loginMethod'"
             @click="otherLoginMethod(item)">
          <svg-icon :icon-class="item.label"/>
        </div>
      </div>
    </el-card>
  </div>
</template>

<script>
import {preOtherAuthUrl, unBindThirdAccount} from "@/api/login";
import {thirdAccountList} from "@/api/system/thirdAccount";

export default {
  name: "thirdAccount",
  dicts: ['user_third_status', 'third_account_type'],
  data() {
    return {
      alreadyBindList: [],
      tableData: [],
    }
  },
  methods: {
    otherLoginMethod(item) {
      let that = this;
      that.$modal.loading();
      preOtherAuthUrl(null, "bind", item.value).then(res => {
        location.href = res.authorizeUrl;
      }).finally(res => {
        this.$modal.closeLoading();
      })
    },
    unbind(data) {
      let that = this;
      that.$confirm('确认取消绑定吗?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        // 打开遮罩层
        that.$modal.loading();
        let params = {
          bindType: data.bindType
        };
        unBindThirdAccount(params).then(res => {
          that.$modal.msgSuccess(res.msg);
          that.getOtherList();
        }).finally(res => {
          // 关闭遮罩层
          that.$modal.closeLoading();
        })
      }).catch(() => {
        // 点取消的提示
        return
      })
    },
    getOtherList() {
      let that = this;
      thirdAccountList().then(res => {
        that.tableData = res.rows;
        that.alreadyBindList = [];
        that.tableData.some(item => {
          if (item.bindFlag == '1') {
            this.alreadyBindList.push(item.bindType);
          }
        })
        that.dict.type['third_account_type'].some((item, index) => {
          if (that.alreadyBindList.includes(item.value)) {
            that.dict.type['third_account_type'][index].show = false;
          } else {
            that.dict.type['third_account_type'][index].show = true;
          }
        })
      })
    },
    getLogoUrl(bindType) {
      let logo = "";
      this.dict.type['third_account_type'].forEach(item => {
        if (item.value == bindType) {
          logo = item.label;
        }
      })
      return logo;
    }
  },
  mounted() {
    let that = this;
    let token = this.$route.query.callback_token;
    let loginType = this.$route.query.callback_login_type;
    let uuid = this.$route.query.callback_uuid;
    if (token != undefined && token != null && token != '' && token != undefined && loginType != null && loginType != '') {
      that.$modal.loading();
      const formBody = {
        token: token,
        loginType: loginType,
        uuid: uuid
      }
      this.$modal.loading("正在登录中,请稍后");
      this.$store.dispatch("otherLogin", formBody).then((res) => {
        this.$modal.msgSuccess(res.msg);
        that.getOtherList();
      }).catch((res) => {
      }).finally(() => {
        this.$modal.closeLoading();
        let newUrl = window.location.href.substr(0, window.location.href.indexOf("callback_token"))
        window.history.replaceState(null, null, newUrl);
      });
    }
  },
  created() {
    this.getOtherList();
  }
}
</script>

<style scoped lang="scss">
.otherLogo {
  width: 40px;
  height: 40px;
  border-radius: 50%;
}

.loginMethods {
  display: flex;
  justify-content: left;
  align-content: center;
  gap: 20px;

  .loginMethod {
    font-size: 35px;
    cursor: pointer;

    img {
      border-radius: 80%;
      width: 100%;
      height: 100%;
    }

  }
}
</style>

5.2:在src/views/system/user/profile/index.vue里面引用该组件

<el-col :span="18" :xs="24" class="box">
  <third-account></third-account>
</el-col>

感谢阅读,欢迎您去我的个人博客看看哦文章来源地址https://www.toymoban.com/news/detail-813242.html

到了这里,关于若依实现第三方登录,史上最全保姆级教程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • Springboot整合第三方登录

    Springboot整合第三方登录 为什么采用第三方登录 ​ 采用第三方登录可以避免重新注册账号的繁琐,也不需要再为密码和昵称发愁,而第三方登录有一个比较好用的包,里面整合了多种第三方登录,开箱即用,非常方便。就是JustAuth,网址https://www.justauth.cn/。 整合第三方登录

    2024年02月09日
    浏览(43)
  • 实现 Google 第三方授权登录

    最近做项目要实现Google的第三方登录,这简单的记录一下。 目前Google的第三方登录有很多方案,且官方提供SDK方便接入。但是我这个项目同时要实现网页和客户端。所以选择了 Google OAuth 2.0 的方案。 当然,也可以 《实现 Facebook 第三方授权登录》 Google 的 OAuth 2.0 流程 首先

    2024年02月09日
    浏览(44)
  • 微信小程序第三方登录

    目录 小程序第三方登录操作流程如下: 1.第一步 2.第二步 2.第三步 4.第四步 5.第五步 注意:如果第一步没打印出来,看看微信模拟器上的Id有没有更改,或则去源码试图,weixinId更改 进入uniapp官网=Api=第三方服务=登录=微信小程序登录 创建一个触发事件,获取头像和名称 调用

    2024年02月13日
    浏览(71)
  • PHP Twitter 推特 第三方登录

    twitter登录文档 开发者平台 申请成为开发流程按引导操作就可以了, 但是要注意信息填写要真实完善的信息, 否则容易被拒绝(被拒绝可能不能二次申请, 之前不能, 现在不知道能不能) 目前推特一个号只能开通一个免费应用, 可付费开通多个 设置基础信息 User authentication setting

    2024年04月16日
    浏览(35)
  • 若依 关于 springsecurity 不用密码登录,自定义第三方登录、免登录

    用的是若依的前后端分离的版本,项目接口是给小程序用 openid 直接免登录 找到登录方法 他这是根据用户名和密码进行比对、由于密码没办法转换成明文 只能改成如下方法免登录

    2024年02月07日
    浏览(51)
  • uniapp 对接谷歌第三方登录

    1.登录谷歌开发者后台 https://console.developers.google.com/ 2.添加凭证 3.拿到客户端id后,项目中配置google登录:  示例代码:

    2024年04月29日
    浏览(43)
  • 使用开源项目JustAuth完成第三方登录

    JustAuth项目源码地址:https://github.com/justauth/JustAuth JustAuth文档地址:https://justauth.wiki/guide/quickstart/oauth/ 此demo的项目地址:xfeng520/JustAuthDemo (gitee.com) 开发者 指使用 JustAuth 的开发者 第三方 指开发者对接的第三方网站,比如:QQ平台、微信平台、微博平台 用户 指最终服务的真实

    2023年04月22日
    浏览(81)
  • 全网最全,基于docker 创建的Minio容器配置Https 访问,不使用第三方服务

    1.需要一个域名ssl证书 阿里云有免费的,可以使用,推荐链接: https://yundunnext.console.aliyun.com/?spm=a2c4g.11186623.0.0.3efc4f2epEe03yp=cas#/overview/cn-hangzhou 2.使用docker的主机模式     --network=host 3.在宿主机上的  /etc/hosts  添加域名映射  127.0.0.1     minio.demo.com 4.将证书配置挂载到mini

    2024年04月13日
    浏览(45)
  • 前端使用firebase配置第三方登录介绍(谷歌登录,facebook登录等)

    点此处去 firebase 官网 点此处去 web端的谷歌登录文档 点此处去 facebook开发者官网链接 首先注册一个账号登录firebase(可以使用谷歌账号登录) 然后创建项目(走默认配置就行了) 添加应用(走默认配置),如图所示,本文介绍web应用。 应用添加完毕后走项目设置-如下图(

    2024年04月13日
    浏览(44)
  • OAuth 2.0 协议介绍【实现 GitHub 第三方登录】

    OAuth(是 Open Authorization 开放授权的缩写),在全世界得到广泛应用,目前的版本是2.0版。 本文会对OAuth 2.0的设计思路和运行流程,做一个简明通俗的解释,主要参考材料为RFC 6749。 OAuth 2.0 是一个开放标准,用于授权用户访问另一个应用程序的资源,而无需将用户的凭据(比如

    2024年02月20日
    浏览(64)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包