Commit 8cead0869eb3b29afd6f57ba660abe394d12e342

Authored by 芋道源码
Committed by Gitee
2 parents b336655a 8dbd6143

!51 用户前台的社交登陆的部分实现

Merge pull request !51 from 芋道源码/feature/user-social
Showing 55 changed files with 859 additions and 160 deletions
mini-program-test/.eslintrc.js 0 → 100755
  1 +/*
  2 + * Eslint config file
  3 + * Documentation: https://eslint.org/docs/user-guide/configuring/
  4 + * Install the Eslint extension before using this feature.
  5 + */
  6 +module.exports = {
  7 + env: {
  8 + es6: true,
  9 + browser: true,
  10 + node: true,
  11 + },
  12 + ecmaFeatures: {
  13 + modules: true,
  14 + },
  15 + parserOptions: {
  16 + ecmaVersion: 2018,
  17 + sourceType: 'module',
  18 + },
  19 + globals: {
  20 + wx: true,
  21 + App: true,
  22 + Page: true,
  23 + getCurrentPages: true,
  24 + getApp: true,
  25 + Component: true,
  26 + requirePlugin: true,
  27 + requireMiniProgram: true,
  28 + },
  29 + // extends: 'eslint:recommended',
  30 + rules: {},
  31 +}
mini-program-test/README.md 0 → 100644
  1 +临时项目,作为测试微信小程序登陆之用
mini-program-test/app.js 0 → 100755
  1 +// app.js
  2 +App({
  3 + onLaunch() {
  4 + // 展示本地存储能力
  5 + const logs = wx.getStorageSync('logs') || []
  6 + logs.unshift(Date.now())
  7 + wx.setStorageSync('logs', logs)
  8 +
  9 + // 登录
  10 + wx.login({
  11 + success: res => {
  12 + // 发送 res.code 到后台换取 openId, sessionKey, unionId
  13 + }
  14 + })
  15 + },
  16 + globalData: {
  17 + userInfo: null
  18 + }
  19 +})
mini-program-test/app.json 0 → 100755
  1 +{
  2 + "pages":[
  3 + "pages/index/index",
  4 + "pages/logs/logs"
  5 + ],
  6 + "window":{
  7 + "backgroundTextStyle":"light",
  8 + "navigationBarBackgroundColor": "#fff",
  9 + "navigationBarTitleText": "Weixin",
  10 + "navigationBarTextStyle":"black"
  11 + },
  12 + "style": "v2",
  13 + "sitemapLocation": "sitemap.json"
  14 +}
mini-program-test/app.wxss 0 → 100755
  1 +/**app.wxss**/
  2 +.container {
  3 + height: 100%;
  4 + display: flex;
  5 + flex-direction: column;
  6 + align-items: center;
  7 + justify-content: space-between;
  8 + padding: 200rpx 0;
  9 + box-sizing: border-box;
  10 +}
mini-program-test/pages/index/index.js 0 → 100755
  1 +// index.js
  2 +
  3 +const common=require('../../utils/common.js')
  4 +// 获取应用实例
  5 +const app = getApp()
  6 +
  7 +Page({
  8 + data: {
  9 + motto: 'Hello World',
  10 + userInfo: {},
  11 + hasUserInfo: false,
  12 + canIUse: wx.canIUse('button.open-type.getUserInfo'),
  13 + canIUseGetUserProfile: false,
  14 + canIUseOpenData: wx.canIUse('open-data.type.userAvatarUrl') && wx.canIUse('open-data.type.userNickName'), // 如需尝试获取用户信息可改为false
  15 + holderText: 'to be auth'
  16 + },
  17 + // 事件处理函数
  18 + bindViewTap() {
  19 + wx.navigateTo({
  20 + url: '../logs/logs'
  21 + })
  22 + },
  23 + onLoad() {
  24 + if (wx.getUserProfile) {
  25 + this.setData({
  26 + canIUseGetUserProfile: true
  27 + })
  28 + }
  29 + },
  30 + getUserProfile(e) {
  31 + // 推荐使用wx.getUserProfile获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认,开发者妥善保管用户快速填写的头像昵称,避免重复弹窗
  32 + wx.getUserProfile({
  33 + desc: '展示用户信息', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
  34 + success: (res) => {
  35 + console.log(res)
  36 + this.setData({
  37 + userInfo: res.userInfo,
  38 + hasUserInfo: true
  39 + })
  40 + }
  41 + })
  42 + },
  43 + getUserInfo(e) {
  44 + // 不推荐使用getUserInfo获取用户信息,预计自2021年4月13日起,getUserInfo将不再弹出弹窗,并直接返回匿名的用户个人信息
  45 + console.log(e)
  46 + this.setData({
  47 + userInfo: e.detail.userInfo,
  48 + hasUserInfo: true
  49 + })
  50 + },
  51 + // 小程序登录 https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html
  52 + wxLogin(e){
  53 + let page=this;
  54 + wx.login({
  55 + success (res) {
  56 + console.log("res:")
  57 + console.log(res)
  58 + if (res.code) {
  59 + //发起网络请求
  60 + console.log('发起网络请求'+common.baseurl)
  61 + wx.request({
  62 + url: common.baseurl+'/api/social-login2',
  63 + method: "POST",
  64 + data: {
  65 + code: res.code,
  66 + state: 'empty',
  67 + type: 33,
  68 + username: '15601691300',
  69 + password: 'admin123'
  70 + },
  71 + header: {
  72 + 'content-type': 'application/json' // 默认值
  73 + },
  74 + success: function(res) {
  75 + console.log(res.data)
  76 + let holder="auth success, token:"+res.data.data.token
  77 + page.setData({holderText: holder})
  78 + },
  79 + fail: function(data){
  80 + console.error("请求出错");
  81 + console.error(data)
  82 + }
  83 +
  84 + })
  85 + } else {
  86 + console.log('登录失败!' + res.errMsg)
  87 + }
  88 + }
  89 + })
  90 + }
  91 +})
mini-program-test/pages/index/index.json 0 → 100755
  1 +{
  2 + "usingComponents": {}
  3 +}
0 \ No newline at end of file 4 \ No newline at end of file
mini-program-test/pages/index/index.wxml 0 → 100755
  1 +<!--index.wxml-->
  2 +<view class="container">
  3 + <view class="userinfo">
  4 + <block wx:if="{{canIUseOpenData}}">
  5 +
  6 +
  7 + </block>
  8 + <block wx:elif="{{!hasUserInfo}}">
  9 + <button wx:if="{{canIUseGetUserProfile}}" bindtap="getUserProfile"> 获取头像昵称 </button>
  10 + <button wx:elif="{{canIUse}}" open-type="getUserInfo" bindgetuserinfo="getUserInfo"> 获取头像昵称 </button>
  11 + <view wx:else> 请使用1.4.4及以上版本基础库 </view>
  12 + </block>
  13 + <block wx:else>
  14 + <image bindtap="bindViewTap" class="userinfo-avatar" src="{{userInfo.avatarUrl}}" mode="cover"></image>
  15 + <text class="userinfo-nickname">{{userInfo.nickName}}</text>
  16 + </block>
  17 + </view>
  18 + <view class="usermotto">
  19 +
  20 + </view>
  21 +
  22 +
  23 +
  24 + <text style="position: relative; left: 1rpx; top: -476rpx">授权登录测试1024</text>
  25 +
  26 + <button style="position: relative; left: 0rpx; top: -361rpx" type="primary" id="login-button" bindtap="wxLogin">点击授权登录</button>
  27 +
  28 + <text style="position: relative; left: 1rpx; top: -272rpx" id="login-user-id">{{holderText}}</text>
  29 +</view>
mini-program-test/pages/index/index.wxss 0 → 100755
  1 +/**index.wxss**/
  2 +.userinfo {
  3 + display: flex;
  4 + flex-direction: column;
  5 + align-items: center;
  6 + color: #aaa;
  7 +}
  8 +
  9 +.userinfo-avatar {
  10 + overflow: hidden;
  11 + width: 128rpx;
  12 + height: 128rpx;
  13 + margin: 20rpx;
  14 + border-radius: 50%;
  15 +}
  16 +
  17 +.usermotto {
  18 + margin-top: 200px;
  19 +}
0 \ No newline at end of file 20 \ No newline at end of file
mini-program-test/pages/logs/logs.js 0 → 100755
  1 +// logs.js
  2 +const util = require('../../utils/util.js')
  3 +
  4 +Page({
  5 + data: {
  6 + logs: []
  7 + },
  8 + onLoad() {
  9 + this.setData({
  10 + logs: (wx.getStorageSync('logs') || []).map(log => {
  11 + return {
  12 + date: util.formatTime(new Date(log)),
  13 + timeStamp: log
  14 + }
  15 + })
  16 + })
  17 + }
  18 +})
mini-program-test/pages/logs/logs.json 0 → 100755
  1 +{
  2 + "navigationBarTitleText": "查看启动日志",
  3 + "usingComponents": {}
  4 +}
0 \ No newline at end of file 5 \ No newline at end of file
mini-program-test/pages/logs/logs.wxml 0 → 100755
  1 +<!--logs.wxml-->
  2 +<view class="container log-list">
  3 + <block wx:for="{{logs}}" wx:key="timeStamp" wx:for-item="log">
  4 + <text class="log-item">{{index + 1}}. {{log.date}}</text>
  5 + </block>
  6 +</view>
mini-program-test/pages/logs/logs.wxss 0 → 100755
  1 +.log-list {
  2 + display: flex;
  3 + flex-direction: column;
  4 + padding: 40rpx;
  5 +}
  6 +.log-item {
  7 + margin: 10rpx;
  8 +}
mini-program-test/project.config.json 0 → 100755
  1 +{
  2 + "description": "项目配置文件",
  3 + "packOptions": {
  4 + "ignore": [
  5 + {
  6 + "type": "file",
  7 + "value": ".eslintrc.js"
  8 + }
  9 + ]
  10 + },
  11 + "setting": {
  12 + "bundle": false,
  13 + "userConfirmedBundleSwitch": false,
  14 + "urlCheck": true,
  15 + "scopeDataCheck": false,
  16 + "coverView": true,
  17 + "es6": true,
  18 + "postcss": true,
  19 + "compileHotReLoad": false,
  20 + "lazyloadPlaceholderEnable": false,
  21 + "preloadBackgroundData": false,
  22 + "minified": true,
  23 + "autoAudits": false,
  24 + "newFeature": false,
  25 + "uglifyFileName": false,
  26 + "uploadWithSourceMap": true,
  27 + "useIsolateContext": true,
  28 + "nodeModules": false,
  29 + "enhance": true,
  30 + "useMultiFrameRuntime": true,
  31 + "useApiHook": true,
  32 + "useApiHostProcess": true,
  33 + "showShadowRootInWxmlPanel": true,
  34 + "packNpmManually": false,
  35 + "enableEngineNative": false,
  36 + "packNpmRelationList": [],
  37 + "minifyWXSS": true,
  38 + "showES6CompileOption": false,
  39 + "minifyWXML": true
  40 + },
  41 + "compileType": "miniprogram",
  42 + "libVersion": "2.19.4",
  43 + "appid": "wx44d047d87e6284d8",
  44 + "appid1": "wx63c280fe3248a3e7",
  45 + "projectname": "mini-program-test",
  46 + "debugOptions": {
  47 + "hidedInDevtools": []
  48 + },
  49 + "scripts": {},
  50 + "staticServerOptions": {
  51 + "baseURL": "",
  52 + "servePath": ""
  53 + },
  54 + "isGameTourist": false,
  55 + "condition": {
  56 + "search": {
  57 + "list": []
  58 + },
  59 + "conversation": {
  60 + "list": []
  61 + },
  62 + "game": {
  63 + "list": []
  64 + },
  65 + "plugin": {
  66 + "list": []
  67 + },
  68 + "gamePlugin": {
  69 + "list": []
  70 + },
  71 + "miniprogram": {
  72 + "list": []
  73 + }
  74 + }
  75 +}
0 \ No newline at end of file 76 \ No newline at end of file
mini-program-test/sitemap.json 0 → 100755
  1 +{
  2 + "desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
  3 + "rules": [{
  4 + "action": "allow",
  5 + "page": "*"
  6 + }]
  7 +}
0 \ No newline at end of file 8 \ No newline at end of file
mini-program-test/utils/common.js 0 → 100755
  1 +module.exports = {
  2 + baseurl: "http://127.0.0.1:28080"
  3 +}
mini-program-test/utils/util.js 0 → 100755
  1 +const formatTime = date => {
  2 + const year = date.getFullYear()
  3 + const month = date.getMonth() + 1
  4 + const day = date.getDate()
  5 + const hour = date.getHours()
  6 + const minute = date.getMinutes()
  7 + const second = date.getSeconds()
  8 +
  9 + return `${[year, month, day].map(formatNumber).join('/')} ${[hour, minute, second].map(formatNumber).join(':')}`
  10 +}
  11 +
  12 +const formatNumber = n => {
  13 + n = n.toString()
  14 + return n[1] ? n : `0${n}`
  15 +}
  16 +
  17 +module.exports = {
  18 + formatTime
  19 +}
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/SysAuthController.java
@@ -8,10 +8,11 @@ import cn.iocoder.yudao.adminserver.modules.system.enums.permission.MenuTypeEnum @@ -8,10 +8,11 @@ import cn.iocoder.yudao.adminserver.modules.system.enums.permission.MenuTypeEnum
8 import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysAuthService; 8 import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysAuthService;
9 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService; 9 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService;
10 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysRoleService; 10 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysRoleService;
11 -import cn.iocoder.yudao.adminserver.modules.system.service.social.SysSocialService;  
12 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; 11 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
  12 +import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialService;
13 import cn.iocoder.yudao.coreservice.modules.system.service.user.SysUserCoreService; 13 import cn.iocoder.yudao.coreservice.modules.system.service.user.SysUserCoreService;
14 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 14 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  15 +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
15 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 16 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
16 import cn.iocoder.yudao.framework.common.util.collection.SetUtils; 17 import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
17 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; 18 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
@@ -132,7 +133,7 @@ public class SysAuthController { @@ -132,7 +133,7 @@ public class SysAuthController {
132 @DeleteMapping("/social-unbind") 133 @DeleteMapping("/social-unbind")
133 @ApiOperation("取消社交绑定") 134 @ApiOperation("取消社交绑定")
134 public CommonResult<Boolean> socialUnbind(@RequestBody SysAuthSocialUnbindReqVO reqVO) { 135 public CommonResult<Boolean> socialUnbind(@RequestBody SysAuthSocialUnbindReqVO reqVO) {
135 - socialService.unbindSocialUser(getLoginUserId(), reqVO.getType(), reqVO.getUnionId()); 136 + socialService.unbindSocialUser(getLoginUserId(), reqVO.getType(), reqVO.getUnionId(), UserTypeEnum.ADMIN);
136 return CommonResult.success(true); 137 return CommonResult.success(true);
137 } 138 }
138 139
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthSocialBindReqVO.java
1 package cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth; 1 package cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth;
2 2
3 -import cn.iocoder.yudao.adminserver.modules.system.enums.social.SysSocialTypeEnum; 3 +import cn.iocoder.yudao.coreservice.modules.system.enums.social.SysSocialTypeEnum;
4 import cn.iocoder.yudao.framework.common.validation.InEnum; 4 import cn.iocoder.yudao.framework.common.validation.InEnum;
5 import io.swagger.annotations.ApiModel; 5 import io.swagger.annotations.ApiModel;
6 import io.swagger.annotations.ApiModelProperty; 6 import io.swagger.annotations.ApiModelProperty;
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthSocialLogin2ReqVO.java
1 package cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth; 1 package cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth;
2 2
3 -import cn.iocoder.yudao.adminserver.modules.system.enums.social.SysSocialTypeEnum; 3 +import cn.iocoder.yudao.coreservice.modules.system.enums.social.SysSocialTypeEnum;
4 import cn.iocoder.yudao.framework.common.validation.InEnum; 4 import cn.iocoder.yudao.framework.common.validation.InEnum;
5 import io.swagger.annotations.ApiModel; 5 import io.swagger.annotations.ApiModel;
6 import io.swagger.annotations.ApiModelProperty; 6 import io.swagger.annotations.ApiModelProperty;
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthSocialLoginReqVO.java
1 package cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth; 1 package cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth;
2 2
3 -import cn.iocoder.yudao.adminserver.modules.system.enums.social.SysSocialTypeEnum; 3 +import cn.iocoder.yudao.coreservice.modules.system.enums.social.SysSocialTypeEnum;
4 import cn.iocoder.yudao.framework.common.validation.InEnum; 4 import cn.iocoder.yudao.framework.common.validation.InEnum;
5 import io.swagger.annotations.ApiModel; 5 import io.swagger.annotations.ApiModel;
6 import io.swagger.annotations.ApiModelProperty; 6 import io.swagger.annotations.ApiModelProperty;
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/vo/auth/SysAuthSocialUnbindReqVO.java
1 package cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth; 1 package cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth;
2 2
3 -import cn.iocoder.yudao.adminserver.modules.system.enums.social.SysSocialTypeEnum; 3 +import cn.iocoder.yudao.coreservice.modules.system.enums.social.SysSocialTypeEnum;
4 import cn.iocoder.yudao.framework.common.validation.InEnum; 4 import cn.iocoder.yudao.framework.common.validation.InEnum;
5 import io.swagger.annotations.ApiModel; 5 import io.swagger.annotations.ApiModel;
6 import io.swagger.annotations.ApiModelProperty; 6 import io.swagger.annotations.ApiModelProperty;
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/SysUserProfileController.java
@@ -8,15 +8,16 @@ import cn.iocoder.yudao.adminserver.modules.system.convert.user.SysUserConvert; @@ -8,15 +8,16 @@ import cn.iocoder.yudao.adminserver.modules.system.convert.user.SysUserConvert;
8 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO; 8 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO;
9 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysPostDO; 9 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysPostDO;
10 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleDO; 10 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleDO;
11 -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.social.SysSocialUserDO;  
12 import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysDeptService; 11 import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysDeptService;
13 import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysPostService; 12 import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysPostService;
14 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService; 13 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService;
15 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysRoleService; 14 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysRoleService;
16 -import cn.iocoder.yudao.adminserver.modules.system.service.social.SysSocialService;  
17 import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; 15 import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
  16 +import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.social.SysSocialUserDO;
18 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; 17 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
  18 +import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialService;
19 import cn.iocoder.yudao.coreservice.modules.system.service.user.SysUserCoreService; 19 import cn.iocoder.yudao.coreservice.modules.system.service.user.SysUserCoreService;
  20 +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
20 import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; 21 import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
21 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 22 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
22 import io.swagger.annotations.Api; 23 import io.swagger.annotations.Api;
@@ -77,7 +78,7 @@ public class SysUserProfileController { @@ -77,7 +78,7 @@ public class SysUserProfileController {
77 resp.setPosts(SysUserConvert.INSTANCE.convertList02(posts)); 78 resp.setPosts(SysUserConvert.INSTANCE.convertList02(posts));
78 } 79 }
79 // 获得社交用户信息 80 // 获得社交用户信息
80 - List<SysSocialUserDO> socialUsers = socialService.getSocialUserList(user.getId()); 81 + List<SysSocialUserDO> socialUsers = socialService.getSocialUserList(user.getId(), UserTypeEnum.ADMIN);
81 resp.setSocialUsers(SysUserConvert.INSTANCE.convertList03(socialUsers)); 82 resp.setSocialUsers(SysUserConvert.INSTANCE.convertList03(socialUsers));
82 return success(resp); 83 return success(resp);
83 } 84 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/user/SysUserConvert.java
@@ -7,7 +7,7 @@ import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user.*; @@ -7,7 +7,7 @@ import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user.*;
7 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO; 7 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO;
8 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysPostDO; 8 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysPostDO;
9 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleDO; 9 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleDO;
10 -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.social.SysSocialUserDO; 10 +import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.social.SysSocialUserDO;
11 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; 11 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
12 import org.mapstruct.Mapper; 12 import org.mapstruct.Mapper;
13 import org.mapstruct.factory.Mappers; 13 import org.mapstruct.factory.Mappers;
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/redis/SysRedisKeyConstants.java
@@ -19,12 +19,5 @@ public interface SysRedisKeyConstants { @@ -19,12 +19,5 @@ public interface SysRedisKeyConstants {
19 "captcha_code:%s", // 参数为 uuid 19 "captcha_code:%s", // 参数为 uuid
20 STRING, String.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC); 20 STRING, String.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC);
21 21
22 - RedisKeyDefine SOCIAL_AUTH_USER = new RedisKeyDefine("社交的授权用户",  
23 - "social_auth_user:%d:%s", // 参数为 type,code  
24 - STRING, AuthUser.class, Duration.ofDays(1));  
25 -  
26 - RedisKeyDefine SOCIAL_AUTH_STATE = new RedisKeyDefine("社交的 state",  
27 - "social_auth_state:%s", // 参数为 state  
28 - STRING, String.class, Duration.ofHours(24)); // 值为 state  
29 22
30 } 23 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/SysErrorCodeConstants.java
@@ -89,8 +89,6 @@ public interface SysErrorCodeConstants { @@ -89,8 +89,6 @@ public interface SysErrorCodeConstants {
89 ErrorCode ERROR_CODE_NOT_EXISTS = new ErrorCode(1002013000, "错误码不存在"); 89 ErrorCode ERROR_CODE_NOT_EXISTS = new ErrorCode(1002013000, "错误码不存在");
90 ErrorCode ERROR_CODE_DUPLICATE = new ErrorCode(1002013001, "已经存在编码为【{}】的错误码"); 90 ErrorCode ERROR_CODE_DUPLICATE = new ErrorCode(1002013001, "已经存在编码为【{}】的错误码");
91 91
92 - // ========== 社交模块 1002014000 ==========  
93 - ErrorCode SOCIAL_AUTH_FAILURE = new ErrorCode(1002014000, "社交授权失败,原因是:{}");  
94 - ErrorCode SOCIAL_UNBIND_NOT_SELF = new ErrorCode(1002014001, "社交解绑失败,非当前用户绑定"); 92 +
95 93
96 } 94 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/impl/SysAuthServiceImpl.java
@@ -6,18 +6,18 @@ import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAu @@ -6,18 +6,18 @@ import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAu
6 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthSocialLogin2ReqVO; 6 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthSocialLogin2ReqVO;
7 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthSocialLoginReqVO; 7 import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthSocialLoginReqVO;
8 import cn.iocoder.yudao.adminserver.modules.system.convert.auth.SysAuthConvert; 8 import cn.iocoder.yudao.adminserver.modules.system.convert.auth.SysAuthConvert;
9 -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.social.SysSocialUserDO;  
10 import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginLogTypeEnum; 9 import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginLogTypeEnum;
11 import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginResultEnum; 10 import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginResultEnum;
12 import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysAuthService; 11 import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysAuthService;
13 import cn.iocoder.yudao.adminserver.modules.system.service.common.SysCaptchaService; 12 import cn.iocoder.yudao.adminserver.modules.system.service.common.SysCaptchaService;
14 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService; 13 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService;
15 -import cn.iocoder.yudao.adminserver.modules.system.service.social.SysSocialService;  
16 import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; 14 import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
  15 +import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.social.SysSocialUserDO;
17 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; 16 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
18 import cn.iocoder.yudao.coreservice.modules.system.service.auth.SysUserSessionCoreService; 17 import cn.iocoder.yudao.coreservice.modules.system.service.auth.SysUserSessionCoreService;
19 import cn.iocoder.yudao.coreservice.modules.system.service.logger.SysLoginLogCoreService; 18 import cn.iocoder.yudao.coreservice.modules.system.service.logger.SysLoginLogCoreService;
20 import cn.iocoder.yudao.coreservice.modules.system.service.logger.dto.SysLoginLogCreateReqDTO; 19 import cn.iocoder.yudao.coreservice.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
  20 +import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialService;
21 import cn.iocoder.yudao.coreservice.modules.system.service.user.SysUserCoreService; 21 import cn.iocoder.yudao.coreservice.modules.system.service.user.SysUserCoreService;
22 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 22 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
23 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; 23 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
@@ -75,6 +75,9 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -75,6 +75,9 @@ public class SysAuthServiceImpl implements SysAuthService {
75 @Resource 75 @Resource
76 private SysSocialService socialService; 76 private SysSocialService socialService;
77 77
  78 + // TODO @timfruit:静态枚举类,需要都大写,例如说 USER_TYPE_ENUM;静态变量,放在普通变量前面;这个实践不错哈。
  79 + private static final UserTypeEnum userTypeEnum = UserTypeEnum.ADMIN;
  80 +
78 @Override 81 @Override
79 public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 82 public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
80 // 获取 username 对应的 SysUserDO 83 // 获取 username 对应的 SysUserDO
@@ -198,7 +201,7 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -198,7 +201,7 @@ public class SysAuthServiceImpl implements SysAuthService {
198 201
199 // 如果未绑定 SysSocialUserDO 用户,则无法自动登录,进行报错 202 // 如果未绑定 SysSocialUserDO 用户,则无法自动登录,进行报错
200 String unionId = socialService.getAuthUserUnionId(authUser); 203 String unionId = socialService.getAuthUserUnionId(authUser);
201 - List<SysSocialUserDO> socialUsers = socialService.getAllSocialUserList(reqVO.getType(), unionId); 204 + List<SysSocialUserDO> socialUsers = socialService.getAllSocialUserList(reqVO.getType(), unionId, userTypeEnum);
202 if (CollUtil.isEmpty(socialUsers)) { 205 if (CollUtil.isEmpty(socialUsers)) {
203 throw exception(AUTH_THIRD_LOGIN_NOT_BIND); 206 throw exception(AUTH_THIRD_LOGIN_NOT_BIND);
204 } 207 }
@@ -212,11 +215,10 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -212,11 +215,10 @@ public class SysAuthServiceImpl implements SysAuthService {
212 215
213 // 创建 LoginUser 对象 216 // 创建 LoginUser 对象
214 LoginUser loginUser = SysAuthConvert.INSTANCE.convert(user); 217 LoginUser loginUser = SysAuthConvert.INSTANCE.convert(user);
215 - // TODO 芋艿:需要改造下,增加各种登录方式  
216 loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表 218 loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表
217 219
218 // 绑定社交用户(更新) 220 // 绑定社交用户(更新)
219 - socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser); 221 + socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser, userTypeEnum);
220 222
221 // 缓存登录用户到 Redis 中,返回 sessionId 编号 223 // 缓存登录用户到 Redis 中,返回 sessionId 编号
222 return userSessionCoreService.createUserSession(loginUser, userIp, userAgent); 224 return userSessionCoreService.createUserSession(loginUser, userIp, userAgent);
@@ -233,7 +235,7 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -233,7 +235,7 @@ public class SysAuthServiceImpl implements SysAuthService {
233 loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表 235 loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表
234 236
235 // 绑定社交用户(新增) 237 // 绑定社交用户(新增)
236 - socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser); 238 + socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser, userTypeEnum);
237 239
238 // 缓存登录用户到 Redis 中,返回 sessionId 编号 240 // 缓存登录用户到 Redis 中,返回 sessionId 编号
239 return userSessionCoreService.createUserSession(loginUser, userIp, userAgent); 241 return userSessionCoreService.createUserSession(loginUser, userIp, userAgent);
@@ -246,7 +248,7 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -246,7 +248,7 @@ public class SysAuthServiceImpl implements SysAuthService {
246 Assert.notNull(authUser, "授权用户不为空"); 248 Assert.notNull(authUser, "授权用户不为空");
247 249
248 // 绑定社交用户(新增) 250 // 绑定社交用户(新增)
249 - socialService.bindSocialUser(userId, reqVO.getType(), authUser); 251 + socialService.bindSocialUser(userId, reqVO.getType(), authUser, userTypeEnum);
250 } 252 }
251 253
252 @Override 254 @Override
@@ -267,7 +269,7 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -267,7 +269,7 @@ public class SysAuthServiceImpl implements SysAuthService {
267 reqDTO.setLogType(SysLoginLogTypeEnum.LOGOUT_SELF.getType()); 269 reqDTO.setLogType(SysLoginLogTypeEnum.LOGOUT_SELF.getType());
268 reqDTO.setTraceId(TracerUtils.getTraceId()); 270 reqDTO.setTraceId(TracerUtils.getTraceId());
269 reqDTO.setUserId(userId); 271 reqDTO.setUserId(userId);
270 - reqDTO.setUserType(UserTypeEnum.ADMIN.getValue()); 272 + reqDTO.setUserType(userTypeEnum.getValue());
271 reqDTO.setUsername(username); 273 reqDTO.setUsername(username);
272 reqDTO.setUserAgent(ServletUtils.getUserAgent()); 274 reqDTO.setUserAgent(ServletUtils.getUserAgent());
273 reqDTO.setUserIp(ServletUtils.getClientIP()); 275 reqDTO.setUserIp(ServletUtils.getClientIP());
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/SysAuthServiceImplTest.java
@@ -7,11 +7,11 @@ import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginResultEn @@ -7,11 +7,11 @@ import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginResultEn
7 import cn.iocoder.yudao.adminserver.modules.system.service.auth.impl.SysAuthServiceImpl; 7 import cn.iocoder.yudao.adminserver.modules.system.service.auth.impl.SysAuthServiceImpl;
8 import cn.iocoder.yudao.adminserver.modules.system.service.common.SysCaptchaService; 8 import cn.iocoder.yudao.adminserver.modules.system.service.common.SysCaptchaService;
9 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService; 9 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService;
10 -import cn.iocoder.yudao.adminserver.modules.system.service.social.SysSocialService;  
11 import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; 10 import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
12 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; 11 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
13 import cn.iocoder.yudao.coreservice.modules.system.service.auth.SysUserSessionCoreService; 12 import cn.iocoder.yudao.coreservice.modules.system.service.auth.SysUserSessionCoreService;
14 import cn.iocoder.yudao.coreservice.modules.system.service.logger.SysLoginLogCoreService; 13 import cn.iocoder.yudao.coreservice.modules.system.service.logger.SysLoginLogCoreService;
  14 +import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialService;
15 import cn.iocoder.yudao.coreservice.modules.system.service.user.SysUserCoreService; 15 import cn.iocoder.yudao.coreservice.modules.system.service.user.SysUserCoreService;
16 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 16 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
17 import cn.iocoder.yudao.framework.security.core.LoginUser; 17 import cn.iocoder.yudao.framework.security.core.LoginUser;
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/social/SysSocialServiceTest.java
1 package cn.iocoder.yudao.adminserver.modules.system.service.social; 1 package cn.iocoder.yudao.adminserver.modules.system.service.social;
2 2
3 import cn.iocoder.yudao.adminserver.BaseDbAndRedisUnitTest; 3 import cn.iocoder.yudao.adminserver.BaseDbAndRedisUnitTest;
4 -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.social.SysSocialUserDO;  
5 -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.social.SysSocialUserMapper;  
6 -import cn.iocoder.yudao.adminserver.modules.system.dal.redis.social.SysSocialAuthUserRedisDAO;  
7 -import cn.iocoder.yudao.adminserver.modules.system.enums.social.SysSocialTypeEnum;  
8 -import cn.iocoder.yudao.adminserver.modules.system.service.social.impl.SysSocialServiceImpl; 4 +import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.social.SysSocialUserDO;
  5 +import cn.iocoder.yudao.coreservice.modules.system.dal.mysql.social.SysSocialUserMapper;
  6 +import cn.iocoder.yudao.coreservice.modules.system.dal.redis.social.SysSocialAuthUserRedisDAO;
  7 +import cn.iocoder.yudao.coreservice.modules.system.enums.social.SysSocialTypeEnum;
  8 +import cn.iocoder.yudao.coreservice.modules.system.service.social.impl.SysSocialServiceImpl;
9 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; 9 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
10 import com.xkcoding.justauth.AuthRequestFactory; 10 import com.xkcoding.justauth.AuthRequestFactory;
11 import me.zhyd.oauth.model.AuthUser; 11 import me.zhyd.oauth.model.AuthUser;
@@ -23,6 +23,7 @@ import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId @@ -23,6 +23,7 @@ import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId
23 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; 23 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
24 import static org.junit.jupiter.api.Assertions.assertEquals; 24 import static org.junit.jupiter.api.Assertions.assertEquals;
25 25
  26 +// TODO @timfruit:这个单元测试,挪到 yudao-core-service
26 /** 27 /**
27 * {@link SysSocialServiceImpl} 的单元测试类 28 * {@link SysSocialServiceImpl} 的单元测试类
28 * 29 *
@@ -53,7 +54,7 @@ public class SysSocialServiceTest extends BaseDbAndRedisUnitTest { @@ -53,7 +54,7 @@ public class SysSocialServiceTest extends BaseDbAndRedisUnitTest {
53 // mock 方法 54 // mock 方法
54 55
55 // 调用 56 // 调用
56 - socialService.bindSocialUser(userId, type, authUser); 57 + socialService.bindSocialUser(userId, type, authUser, UserTypeEnum.ADMIN);
57 // 断言 58 // 断言
58 List<SysSocialUserDO> socialUsers = socialUserMapper.selectList("user_id", userId); 59 List<SysSocialUserDO> socialUsers = socialUserMapper.selectList("user_id", userId);
59 assertEquals(1, socialUsers.size()); 60 assertEquals(1, socialUsers.size());
@@ -78,7 +79,7 @@ public class SysSocialServiceTest extends BaseDbAndRedisUnitTest { @@ -78,7 +79,7 @@ public class SysSocialServiceTest extends BaseDbAndRedisUnitTest {
78 // mock 方法 79 // mock 方法
79 80
80 // 调用 81 // 调用
81 - socialService.bindSocialUser(userId, type, authUser); 82 + socialService.bindSocialUser(userId, type, authUser, UserTypeEnum.ADMIN);
82 // 断言 83 // 断言
83 List<SysSocialUserDO> socialUsers = socialUserMapper.selectList("user_id", userId); 84 List<SysSocialUserDO> socialUsers = socialUserMapper.selectList("user_id", userId);
84 assertEquals(1, socialUsers.size()); 85 assertEquals(1, socialUsers.size());
@@ -103,7 +104,7 @@ public class SysSocialServiceTest extends BaseDbAndRedisUnitTest { @@ -103,7 +104,7 @@ public class SysSocialServiceTest extends BaseDbAndRedisUnitTest {
103 // mock 方法 104 // mock 方法
104 105
105 // 调用 106 // 调用
106 - socialService.bindSocialUser(userId, type, authUser); 107 + socialService.bindSocialUser(userId, type, authUser, UserTypeEnum.ADMIN);
107 // 断言 108 // 断言
108 List<SysSocialUserDO> socialUsers = socialUserMapper.selectList("user_id", userId); 109 List<SysSocialUserDO> socialUsers = socialUserMapper.selectList("user_id", userId);
109 assertEquals(1, socialUsers.size()); 110 assertEquals(1, socialUsers.size());
@@ -140,7 +141,7 @@ public class SysSocialServiceTest extends BaseDbAndRedisUnitTest { @@ -140,7 +141,7 @@ public class SysSocialServiceTest extends BaseDbAndRedisUnitTest {
140 String newUnionId = oldSocialUser.getUnionId(); 141 String newUnionId = oldSocialUser.getUnionId();
141 142
142 // 调用 143 // 调用
143 - socialService.unbindOldSocialUser(userId, type, newUnionId); 144 + socialService.unbindOldSocialUser(userId, type, newUnionId, UserTypeEnum.ADMIN);
144 // 断言 145 // 断言
145 assertEquals(1L, socialUserMapper.selectCount(null).longValue()); 146 assertEquals(1L, socialUserMapper.selectCount(null).longValue());
146 } 147 }
@@ -163,7 +164,7 @@ public class SysSocialServiceTest extends BaseDbAndRedisUnitTest { @@ -163,7 +164,7 @@ public class SysSocialServiceTest extends BaseDbAndRedisUnitTest {
163 String newUnionId = randomString(10); 164 String newUnionId = randomString(10);
164 165
165 // 调用 166 // 调用
166 - socialService.unbindOldSocialUser(userId, type, newUnionId); 167 + socialService.unbindOldSocialUser(userId, type, newUnionId, UserTypeEnum.ADMIN);
167 // 断言 168 // 断言
168 assertEquals(0L, socialUserMapper.selectCount(null).longValue()); 169 assertEquals(0L, socialUserMapper.selectCount(null).longValue());
169 } 170 }
yudao-core-service/pom.xml
@@ -95,6 +95,13 @@ @@ -95,6 +95,13 @@
95 <groupId>com.google.guava</groupId> 95 <groupId>com.google.guava</groupId>
96 <artifactId>guava</artifactId> 96 <artifactId>guava</artifactId>
97 </dependency> 97 </dependency>
  98 +
  99 + <!-- 三方云服务相关 -->
  100 + <dependency>
  101 + <groupId>com.xkcoding.justauth</groupId>
  102 + <artifactId>justauth-spring-boot-starter</artifactId>
  103 + </dependency>
  104 +
98 </dependencies> 105 </dependencies>
99 106
100 </project> 107 </project>
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/compent/justauth/AuthExtendSource.java 0 → 100644
  1 +package cn.iocoder.yudao.coreservice.modules.system.compent.justauth;
  2 +
  3 +import me.zhyd.oauth.config.AuthSource;
  4 +
  5 +public enum AuthExtendSource implements AuthSource {
  6 +
  7 + /**
  8 + * 微信小程序授权登录
  9 + */
  10 + WECHAT_MINI_PROGRAM{
  11 + @Override
  12 + public String authorize() {
  13 + // https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html
  14 + throw new UnsupportedOperationException("不支持获取授权url, 请使用小程序内置函数wx.login()登录获取code");
  15 + }
  16 +
  17 + @Override
  18 + public String accessToken() {
  19 + // https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html
  20 + // 获取openid, unionid , session_key
  21 + return "https://api.weixin.qq.com/sns/jscode2session";
  22 + }
  23 +
  24 + @Override
  25 + public String userInfo() {
  26 + //https://developers.weixin.qq.com/miniprogram/dev/api/open-api/user-info/wx.getUserProfile.html
  27 + throw new UnsupportedOperationException("不支持获取用户信息url, 请使用小程序内置函数wx.getUserProfile()获取用户信息");
  28 + }
  29 + }
  30 +
  31 + ;
  32 +
  33 +}
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/compent/justauth/AuthExtendToken.java 0 → 100644
  1 +package cn.iocoder.yudao.coreservice.modules.system.compent.justauth;
  2 +
  3 +import lombok.*;
  4 +import me.zhyd.oauth.model.AuthToken;
  5 +
  6 +/**
  7 + * TODO @timfruit:类注释
  8 + * @author timfruit
  9 + * @date 2021-10-29
  10 + */
  11 +@Getter
  12 +@Setter
  13 +@NoArgsConstructor
  14 +@AllArgsConstructor
  15 +public class AuthExtendToken extends AuthToken {
  16 +
  17 + /**
  18 + * 微信小程序 会话密钥
  19 + */
  20 + private String miniSessionKey;
  21 +
  22 +}
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/compent/justauth/AuthWeChatMiniProgramRequest.java 0 → 100644
  1 +package cn.iocoder.yudao.coreservice.modules.system.compent.justauth;
  2 +
  3 +import com.alibaba.fastjson.JSONObject;
  4 +import me.zhyd.oauth.cache.AuthStateCache;
  5 +import me.zhyd.oauth.config.AuthConfig;
  6 +import me.zhyd.oauth.exception.AuthException;
  7 +import me.zhyd.oauth.model.AuthCallback;
  8 +import me.zhyd.oauth.model.AuthToken;
  9 +import me.zhyd.oauth.model.AuthUser;
  10 +import me.zhyd.oauth.request.AuthDefaultRequest;
  11 +import me.zhyd.oauth.utils.HttpUtils;
  12 +import me.zhyd.oauth.utils.UrlBuilder;
  13 +
  14 +// TODO @timfruit:新建一个 yudao-spring-boot-starter-biz-social 包,把这个拓展拿进去哈。另外,可以思考下。
  15 +// 1. application-local.yaml 的配置里,justauth.extend.enum-class 能否不配置,而是自动配置好
  16 +// 2. application-local.yaml 的配置里,justauth.extend.extend.config.WECHAT_MINI_PROGRAM 有办法和 justauth.type.WECHAT_MP 持平
  17 +/**
  18 + * 微信小程序登陆
  19 + *
  20 + * @author timfruit
  21 + * @date 2021-10-29
  22 + */
  23 +public class AuthWeChatMiniProgramRequest extends AuthDefaultRequest {
  24 +
  25 + public AuthWeChatMiniProgramRequest(AuthConfig config) {
  26 + super(config, AuthExtendSource.WECHAT_MINI_PROGRAM);
  27 + }
  28 +
  29 + public AuthWeChatMiniProgramRequest(AuthConfig config, AuthStateCache authStateCache) {
  30 + super(config, AuthExtendSource.WECHAT_MINI_PROGRAM, authStateCache);
  31 + }
  32 +
  33 + @Override
  34 + protected AuthToken getAccessToken(AuthCallback authCallback) {
  35 + // https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html
  36 + String response = new HttpUtils(config.getHttpConfig()).get(accessTokenUrl(authCallback.getCode()));
  37 + JSONObject accessTokenObject = JSONObject.parseObject(response); // TODO @timfruit:使用 JsonUtils,项目尽量避免直接使用某个 json 库
  38 +
  39 + this.checkResponse(accessTokenObject);
  40 +
  41 + AuthExtendToken token = new AuthExtendToken();
  42 + token.setMiniSessionKey(accessTokenObject.getString("session_key"));
  43 + token.setOpenId(accessTokenObject.getString("openid"));
  44 + token.setUnionId(accessTokenObject.getString("unionid"));
  45 + return token;
  46 + }
  47 +
  48 + @Override
  49 + protected AuthUser getUserInfo(AuthToken authToken) {
  50 + // https://developers.weixin.qq.com/miniprogram/dev/api/open-api/user-info/wx.getUserProfile.html
  51 + // 如果需要用户信息,需要在小程序调用函数后传给后端
  52 + return AuthUser.builder()
  53 + .uuid(authToken.getOpenId())
  54 + //TODO 是使用默认值,还是有小程序获取用户信息 和 code 一起传过来
  55 + .nickname("")
  56 + .avatar("")
  57 + .token(authToken)
  58 + .source(source.toString())
  59 + .build();
  60 + }
  61 +
  62 + /**
  63 + * 检查响应内容是否正确
  64 + *
  65 + * @param object 请求响应内容
  66 + */
  67 + private void checkResponse(JSONObject object) {
  68 + int code = object.getIntValue("errcode");
  69 + if(code != 0){ // TODO @timfruit:if (code != 0) { ,注意空格
  70 + throw new AuthException(object.getIntValue("errcode"), object.getString("errmsg"));
  71 + }
  72 + }
  73 +
  74 + /**
  75 + * 返回获取 accessToken 的 url
  76 + *
  77 + * @param code 授权码
  78 + * @return 返回获取 accessToken 的 url
  79 + */
  80 + @Override
  81 + protected String accessTokenUrl(String code) {
  82 + return UrlBuilder.fromBaseUrl(source.accessToken())
  83 + .queryParam("appid", config.getClientId())
  84 + .queryParam("secret", config.getClientSecret())
  85 + .queryParam("js_code", code)
  86 + .queryParam("grant_type", "authorization_code")
  87 + .build();
  88 + }
  89 +
  90 +}
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/social/SysSocialUserDO.java renamed to yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/social/SysSocialUserDO.java
1 -package cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.social; 1 +package cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.social;
2 2
3 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; 3 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
4 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; 4 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/social/SysSocialUserMapper.java renamed to yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/mysql/social/SysSocialUserMapper.java
1 -package cn.iocoder.yudao.adminserver.modules.system.dal.mysql.social; 1 +package cn.iocoder.yudao.coreservice.modules.system.dal.mysql.social;
2 2
3 -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.social.SysSocialUserDO; 3 +import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.social.SysSocialUserDO;
4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 5 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
6 import org.apache.ibatis.annotations.Mapper; 6 import org.apache.ibatis.annotations.Mapper;
@@ -8,6 +8,7 @@ import org.apache.ibatis.annotations.Mapper; @@ -8,6 +8,7 @@ import org.apache.ibatis.annotations.Mapper;
8 import java.util.Collection; 8 import java.util.Collection;
9 import java.util.List; 9 import java.util.List;
10 10
  11 +// TODO @timfruit:SysSocialUserCoreMapper 改名,方便区分
11 @Mapper 12 @Mapper
12 public interface SysSocialUserMapper extends BaseMapperX<SysSocialUserDO> { 13 public interface SysSocialUserMapper extends BaseMapperX<SysSocialUserDO> {
13 14
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/redis/SysRedisKeyCoreConstants.java
@@ -2,6 +2,9 @@ package cn.iocoder.yudao.coreservice.modules.system.dal.redis; @@ -2,6 +2,9 @@ package cn.iocoder.yudao.coreservice.modules.system.dal.redis;
2 2
3 import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine; 3 import cn.iocoder.yudao.framework.redis.core.RedisKeyDefine;
4 import cn.iocoder.yudao.framework.security.core.LoginUser; 4 import cn.iocoder.yudao.framework.security.core.LoginUser;
  5 +import me.zhyd.oauth.model.AuthUser;
  6 +
  7 +import java.time.Duration;
5 8
6 import static cn.iocoder.yudao.framework.redis.core.RedisKeyDefine.KeyTypeEnum.STRING; 9 import static cn.iocoder.yudao.framework.redis.core.RedisKeyDefine.KeyTypeEnum.STRING;
7 10
@@ -16,4 +19,11 @@ public interface SysRedisKeyCoreConstants { @@ -16,4 +19,11 @@ public interface SysRedisKeyCoreConstants {
16 "login_user:%s", // 参数为 sessionId 19 "login_user:%s", // 参数为 sessionId
17 STRING, LoginUser.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC); 20 STRING, LoginUser.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC);
18 21
  22 + RedisKeyDefine SOCIAL_AUTH_USER = new RedisKeyDefine("社交登陆的授权用户",
  23 + "social_auth_user:%d:%s", // 参数为 type,code
  24 + STRING, AuthUser.class, Duration.ofDays(1));
  25 +
  26 + RedisKeyDefine SOCIAL_AUTH_STATE = new RedisKeyDefine("社交登陆的 state",
  27 + "social_auth_state:%s", // 参数为 state
  28 + STRING, String.class, Duration.ofHours(24)); // 值为 state
19 } 29 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/redis/social/SysSocialAuthUserRedisDAO.java renamed to yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/redis/social/SysSocialAuthUserRedisDAO.java
1 -package cn.iocoder.yudao.adminserver.modules.system.dal.redis.social; 1 +package cn.iocoder.yudao.coreservice.modules.system.dal.redis.social;
2 2
3 import cn.iocoder.yudao.framework.common.util.json.JsonUtils; 3 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
4 import me.zhyd.oauth.model.AuthCallback; 4 import me.zhyd.oauth.model.AuthCallback;
@@ -8,10 +8,11 @@ import org.springframework.stereotype.Repository; @@ -8,10 +8,11 @@ import org.springframework.stereotype.Repository;
8 8
9 import javax.annotation.Resource; 9 import javax.annotation.Resource;
10 10
11 -import static cn.iocoder.yudao.adminserver.modules.system.dal.redis.SysRedisKeyConstants.SOCIAL_AUTH_USER; 11 +import static cn.iocoder.yudao.coreservice.modules.system.dal.redis.SysRedisKeyCoreConstants.SOCIAL_AUTH_USER;
12 12
  13 +// TODO @timfruit,这里的 AuthUser 还是保留全路径,主要想体现出来,不是自己定义的
13 /** 14 /**
14 - * 社交 {@link me.zhyd.oauth.model.AuthUser} 的 RedisDAO 15 + * 社交 {@link AuthUser} 的 RedisDAO
15 * 16 *
16 * @author 芋道源码 17 * @author 芋道源码
17 */ 18 */
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/enums/SysErrorCodeConstants.java
@@ -18,4 +18,8 @@ public interface SysErrorCodeConstants { @@ -18,4 +18,8 @@ public interface SysErrorCodeConstants {
18 ErrorCode FILE_PATH_EXISTS = new ErrorCode(1006001000, "文件路径已存在"); 18 ErrorCode FILE_PATH_EXISTS = new ErrorCode(1006001000, "文件路径已存在");
19 ErrorCode FILE_NOT_EXISTS = new ErrorCode(1006001002, "文件不存在"); 19 ErrorCode FILE_NOT_EXISTS = new ErrorCode(1006001002, "文件不存在");
20 20
  21 + // ========== 社交模块 1006002000 ==========
  22 + ErrorCode SOCIAL_AUTH_FAILURE = new ErrorCode(1006002000, "社交授权失败,原因是:{}");
  23 + ErrorCode SOCIAL_UNBIND_NOT_SELF = new ErrorCode(1006002001, "社交解绑失败,非当前用户绑定");
  24 +
21 } 25 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/social/SysSocialTypeEnum.java renamed to yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/enums/social/SysSocialTypeEnum.java
1 -package cn.iocoder.yudao.adminserver.modules.system.enums.social; 1 +package cn.iocoder.yudao.coreservice.modules.system.enums.social;
2 2
3 import cn.hutool.core.collection.ListUtil; 3 import cn.hutool.core.collection.ListUtil;
4 import cn.hutool.core.util.ArrayUtil; 4 import cn.hutool.core.util.ArrayUtil;
@@ -18,14 +18,43 @@ import java.util.List; @@ -18,14 +18,43 @@ import java.util.List;
18 @AllArgsConstructor 18 @AllArgsConstructor
19 public enum SysSocialTypeEnum implements IntArrayValuable { 19 public enum SysSocialTypeEnum implements IntArrayValuable {
20 20
21 - GITEE(10, "GITEE"), // https://gitee.com/api/v5/oauth_doc#/  
22 - DINGTALK(20, "DINGTALK"), // https://developers.dingtalk.com/document/app/obtain-identity-credentials  
23 - WECHAT_ENTERPRISE(30, "WECHAT_ENTERPRISE"), // https://xkcoding.com/2019/08/06/use-justauth-integration-wechat-enterprise.html 21 + /**
  22 + * Gitee
  23 + * 文档链接:https://gitee.com/api/v5/oauth_doc#/
  24 + */
  25 + GITEE(10, "GITEE"),
  26 + /**
  27 + * 钉钉
  28 + * 文档链接:https://developers.dingtalk.com/document/app/obtain-identity-credentials
  29 + */
  30 + DINGTALK(20, "DINGTALK"),
  31 +
  32 + /**
  33 + * 企业微信
  34 + * 文档链接:https://xkcoding.com/2019/08/06/use-justauth-integration-wechat-enterprise.html
  35 + */
  36 + WECHAT_ENTERPRISE(30, "WECHAT_ENTERPRISE"),
  37 + /**
  38 + * 微信公众平台 - 移动端 H5
  39 + * 文档链接:https://www.cnblogs.com/juewuzhe/p/11905461.html
  40 + */
  41 + WECHAT_MP(31, "WECHAT_MP"),
  42 + /**
  43 + * 微信开放平台 - 网站应用 PC 端扫码授权登录
  44 + * 文档链接:https://justauth.wiki/guide/oauth/wechat_open/#_2-申请开发者资质认证
  45 + */
  46 + WECHAT_OPEN(32, "WECHAT_OPEN"),
  47 + /**
  48 + * 微信小程序
  49 + * 文档链接:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html
  50 + */
  51 + WECHAT_MINI_PROGRAM(33, "WECHAT_MINI_PROGRAM"),
24 ; 52 ;
25 53
26 public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(SysSocialTypeEnum::getType).toArray(); 54 public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(SysSocialTypeEnum::getType).toArray();
27 55
28 - public static final List<Integer> WECHAT_ALL = ListUtil.toList(WECHAT_ENTERPRISE.type); 56 + public static final List<Integer> WECHAT_ALL = ListUtil.toList(WECHAT_ENTERPRISE.type, WECHAT_MP.type, WECHAT_OPEN.type,
  57 + WECHAT_MINI_PROGRAM.type);
29 58
30 /** 59 /**
31 * 类型 60 * 类型
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/social/SysSocialService.java renamed to yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/social/SysSocialService.java
1 -package cn.iocoder.yudao.adminserver.modules.system.service.social; 1 +package cn.iocoder.yudao.coreservice.modules.system.service.social;
2 2
3 import cn.hutool.core.util.StrUtil; 3 import cn.hutool.core.util.StrUtil;
4 -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.social.SysSocialUserDO;  
5 -import cn.iocoder.yudao.adminserver.modules.system.enums.social.SysSocialTypeEnum; 4 +import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.social.SysSocialUserDO;
  5 +import cn.iocoder.yudao.coreservice.modules.system.enums.social.SysSocialTypeEnum;
  6 +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
6 import cn.iocoder.yudao.framework.common.exception.ServiceException; 7 import cn.iocoder.yudao.framework.common.exception.ServiceException;
7 import me.zhyd.oauth.model.AuthUser; 8 import me.zhyd.oauth.model.AuthUser;
8 9
@@ -14,6 +15,7 @@ import java.util.List; @@ -14,6 +15,7 @@ import java.util.List;
14 * 15 *
15 * @author 芋道源码 16 * @author 芋道源码
16 */ 17 */
  18 +// TODO @timfruit:SysSocialCoreService 改名,方便区分
17 public interface SysSocialService { 19 public interface SysSocialService {
18 20
19 /** 21 /**
@@ -49,7 +51,7 @@ public interface SysSocialService { @@ -49,7 +51,7 @@ public interface SysSocialService {
49 * @param unionId 社交平台的 unionId 51 * @param unionId 社交平台的 unionId
50 * @return 社交用户列表 52 * @return 社交用户列表
51 */ 53 */
52 - List<SysSocialUserDO> getAllSocialUserList(Integer type, String unionId); 54 + List<SysSocialUserDO> getAllSocialUserList(Integer type, String unionId, UserTypeEnum userTypeEnum);
53 55
54 /** 56 /**
55 * 获得指定用户的社交用户列表 57 * 获得指定用户的社交用户列表
@@ -57,7 +59,7 @@ public interface SysSocialService { @@ -57,7 +59,7 @@ public interface SysSocialService {
57 * @param userId 用户编号 59 * @param userId 用户编号
58 * @return 社交用户列表 60 * @return 社交用户列表
59 */ 61 */
60 - List<SysSocialUserDO> getSocialUserList(Long userId); 62 + List<SysSocialUserDO> getSocialUserList(Long userId, UserTypeEnum userTypeEnum);
61 63
62 /** 64 /**
63 * 绑定社交用户 65 * 绑定社交用户
@@ -66,7 +68,7 @@ public interface SysSocialService { @@ -66,7 +68,7 @@ public interface SysSocialService {
66 * @param type 社交平台的类型 {@link SysSocialTypeEnum} 68 * @param type 社交平台的类型 {@link SysSocialTypeEnum}
67 * @param authUser 授权用户 69 * @param authUser 授权用户
68 */ 70 */
69 - void bindSocialUser(Long userId, Integer type, AuthUser authUser); 71 + void bindSocialUser(Long userId, Integer type, AuthUser authUser, UserTypeEnum userTypeEnum);
70 72
71 /** 73 /**
72 * 取消绑定社交用户 74 * 取消绑定社交用户
@@ -75,6 +77,7 @@ public interface SysSocialService { @@ -75,6 +77,7 @@ public interface SysSocialService {
75 * @param type 社交平台的类型 {@link SysSocialTypeEnum} 77 * @param type 社交平台的类型 {@link SysSocialTypeEnum}
76 * @param unionId 社交平台的 unionId 78 * @param unionId 社交平台的 unionId
77 */ 79 */
78 - void unbindSocialUser(Long userId, Integer type, String unionId); 80 + void unbindSocialUser(Long userId, Integer type, String unionId,UserTypeEnum userTypeEnum);
  81 + // TODO @timfruit:逗号后面要有空格;缺少了 @userTypeEnum 的注释,都补充下哈。
79 82
80 } 83 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/social/impl/SysSocialServiceImpl.java renamed to yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/social/impl/SysSocialServiceImpl.java
1 -package cn.iocoder.yudao.adminserver.modules.system.service.social.impl; 1 +package cn.iocoder.yudao.coreservice.modules.system.service.social.impl;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 -import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.social.SysSocialUserDO;  
5 -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.social.SysSocialUserMapper;  
6 -import cn.iocoder.yudao.adminserver.modules.system.dal.redis.social.SysSocialAuthUserRedisDAO;  
7 -import cn.iocoder.yudao.adminserver.modules.system.enums.social.SysSocialTypeEnum;  
8 -import cn.iocoder.yudao.adminserver.modules.system.service.social.SysSocialService; 4 +import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.social.SysSocialUserDO;
  5 +import cn.iocoder.yudao.coreservice.modules.system.dal.mysql.social.SysSocialUserMapper;
  6 +import cn.iocoder.yudao.coreservice.modules.system.dal.redis.social.SysSocialAuthUserRedisDAO;
  7 +import cn.iocoder.yudao.coreservice.modules.system.enums.social.SysSocialTypeEnum;
  8 +import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialService;
9 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; 9 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
10 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 10 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
11 import cn.iocoder.yudao.framework.common.util.http.HttpUtils; 11 import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
@@ -25,8 +25,8 @@ import javax.annotation.Resource; @@ -25,8 +25,8 @@ import javax.annotation.Resource;
25 import java.util.List; 25 import java.util.List;
26 import java.util.Objects; 26 import java.util.Objects;
27 27
28 -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.SOCIAL_AUTH_FAILURE;  
29 -import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.SOCIAL_UNBIND_NOT_SELF; 28 +import static cn.iocoder.yudao.coreservice.modules.system.enums.SysErrorCodeConstants.SOCIAL_AUTH_FAILURE;
  29 +import static cn.iocoder.yudao.coreservice.modules.system.enums.SysErrorCodeConstants.SOCIAL_UNBIND_NOT_SELF;
30 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 30 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
31 import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; 31 import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
32 32
@@ -75,25 +75,25 @@ public class SysSocialServiceImpl implements SysSocialService { @@ -75,25 +75,25 @@ public class SysSocialServiceImpl implements SysSocialService {
75 } 75 }
76 76
77 @Override 77 @Override
78 - public List<SysSocialUserDO> getAllSocialUserList(Integer type, String unionId) { 78 + public List<SysSocialUserDO> getAllSocialUserList(Integer type, String unionId,UserTypeEnum userTypeEnum) {
79 List<Integer> types = SysSocialTypeEnum.getRelationTypes(type); 79 List<Integer> types = SysSocialTypeEnum.getRelationTypes(type);
80 - return socialUserMapper.selectListByTypeAndUnionId(UserTypeEnum.ADMIN.getValue(), types, unionId); 80 + return socialUserMapper.selectListByTypeAndUnionId(userTypeEnum.getValue(), types, unionId);
81 } 81 }
82 82
83 @Override 83 @Override
84 - public List<SysSocialUserDO> getSocialUserList(Long userId) {  
85 - return socialUserMapper.selectListByUserId(UserTypeEnum.ADMIN.getValue(), userId); 84 + public List<SysSocialUserDO> getSocialUserList(Long userId,UserTypeEnum userTypeEnum) {
  85 + return socialUserMapper.selectListByUserId(userTypeEnum.getValue(), userId);
86 } 86 }
87 87
88 @Override 88 @Override
89 @Transactional 89 @Transactional
90 - public void bindSocialUser(Long userId, Integer type, AuthUser authUser) { 90 + public void bindSocialUser(Long userId, Integer type, AuthUser authUser, UserTypeEnum userTypeEnum) {
91 // 获得 unionId 对应的 SysSocialUserDO 列表 91 // 获得 unionId 对应的 SysSocialUserDO 列表
92 String unionId = getAuthUserUnionId(authUser); 92 String unionId = getAuthUserUnionId(authUser);
93 - List<SysSocialUserDO> socialUsers = this.getAllSocialUserList(type, unionId); 93 + List<SysSocialUserDO> socialUsers = this.getAllSocialUserList(type, unionId, userTypeEnum);
94 94
95 // 逻辑一:如果 userId 之前绑定过该 type 的其它账号,需要进行解绑 95 // 逻辑一:如果 userId 之前绑定过该 type 的其它账号,需要进行解绑
96 - this.unbindOldSocialUser(userId, type, unionId); 96 + this.unbindOldSocialUser(userId, type, unionId, userTypeEnum);
97 97
98 // 逻辑二:如果 socialUsers 指定的 userId 改变,需要进行更新 98 // 逻辑二:如果 socialUsers 指定的 userId 改变,需要进行更新
99 // 例如说,一个微信 unionId 对应了多个社交账号,结果其中有个关联了新的 userId,则其它也要跟着修改 99 // 例如说,一个微信 unionId 对应了多个社交账号,结果其中有个关联了新的 userId,则其它也要跟着修改
@@ -112,7 +112,7 @@ public class SysSocialServiceImpl implements SysSocialService { @@ -112,7 +112,7 @@ public class SysSocialServiceImpl implements SysSocialService {
112 .nickname(authUser.getNickname()).avatar(authUser.getAvatar()).rawUserInfo(toJsonString(authUser.getRawUserInfo())) 112 .nickname(authUser.getNickname()).avatar(authUser.getAvatar()).rawUserInfo(toJsonString(authUser.getRawUserInfo()))
113 .build(); 113 .build();
114 if (socialUser == null) { 114 if (socialUser == null) {
115 - saveSocialUser.setUserId(userId).setUserType(UserTypeEnum.ADMIN.getValue()) 115 + saveSocialUser.setUserId(userId).setUserType(userTypeEnum.getValue())
116 .setType(type).setOpenid(authUser.getUuid()).setUnionId(unionId); 116 .setType(type).setOpenid(authUser.getUuid()).setUnionId(unionId);
117 socialUserMapper.insert(saveSocialUser); 117 socialUserMapper.insert(saveSocialUser);
118 } else { 118 } else {
@@ -122,9 +122,9 @@ public class SysSocialServiceImpl implements SysSocialService { @@ -122,9 +122,9 @@ public class SysSocialServiceImpl implements SysSocialService {
122 } 122 }
123 123
124 @Override 124 @Override
125 - public void unbindSocialUser(Long userId, Integer type, String unionId) { 125 + public void unbindSocialUser(Long userId, Integer type, String unionId, UserTypeEnum userTypeEnum) {
126 // 获得 unionId 对应的所有 SysSocialUserDO 社交用户 126 // 获得 unionId 对应的所有 SysSocialUserDO 社交用户
127 - List<SysSocialUserDO> socialUsers = this.getAllSocialUserList(type, unionId); 127 + List<SysSocialUserDO> socialUsers = this.getAllSocialUserList(type, unionId, userTypeEnum);
128 if (CollUtil.isEmpty(socialUsers)) { 128 if (CollUtil.isEmpty(socialUsers)) {
129 return; 129 return;
130 } 130 }
@@ -140,10 +140,10 @@ public class SysSocialServiceImpl implements SysSocialService { @@ -140,10 +140,10 @@ public class SysSocialServiceImpl implements SysSocialService {
140 } 140 }
141 141
142 @VisibleForTesting 142 @VisibleForTesting
143 - public void unbindOldSocialUser(Long userId, Integer type, String newUnionId) { 143 + public void unbindOldSocialUser(Long userId, Integer type, String newUnionId, UserTypeEnum userTypeEnum) {
144 List<Integer> types = SysSocialTypeEnum.getRelationTypes(type); 144 List<Integer> types = SysSocialTypeEnum.getRelationTypes(type);
145 List<SysSocialUserDO> oldSocialUsers = socialUserMapper.selectListByTypeAndUserId( 145 List<SysSocialUserDO> oldSocialUsers = socialUserMapper.selectListByTypeAndUserId(
146 - UserTypeEnum.ADMIN.getValue(), types, userId); 146 + userTypeEnum.getValue(), types, userId);
147 // 如果新老的 unionId 是一致的,说明无需解绑 147 // 如果新老的 unionId 是一致的,说明无需解绑
148 if (CollUtil.isEmpty(oldSocialUsers) || Objects.equals(newUnionId, oldSocialUsers.get(0).getUnionId())) { 148 if (CollUtil.isEmpty(oldSocialUsers) || Objects.equals(newUnionId, oldSocialUsers.get(0).getUnionId())) {
149 return; 149 return;
yudao-dependencies/pom.xml
@@ -410,7 +410,6 @@ @@ -410,7 +410,6 @@
410 <artifactId>yunpian-java-sdk</artifactId> 410 <artifactId>yunpian-java-sdk</artifactId>
411 <version>${yunpian-java-sdk.version}</version> 411 <version>${yunpian-java-sdk.version}</version>
412 </dependency> 412 </dependency>
413 -  
414 <dependency> 413 <dependency>
415 <groupId>com.aliyun</groupId> 414 <groupId>com.aliyun</groupId>
416 <artifactId>aliyun-java-sdk-core</artifactId> 415 <artifactId>aliyun-java-sdk-core</artifactId>
@@ -435,7 +434,7 @@ @@ -435,7 +434,7 @@
435 434
436 <dependency> 435 <dependency>
437 <groupId>com.xkcoding.justauth</groupId> 436 <groupId>com.xkcoding.justauth</groupId>
438 - <artifactId>justauth-spring-boot-starter</artifactId> 437 + <artifactId>justauth-spring-boot-starter</artifactId> <!-- 社交登陆(例如说,个人微信、企业微信等等) -->
439 <version>${justauth.version}</version> 438 <version>${justauth.version}</version>
440 </dependency> 439 </dependency>
441 440
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/enums/social/SysSocialTypeEnum.java deleted
1 -package cn.iocoder.yudao.userserver.modules.member.enums.social;  
2 -  
3 -import cn.hutool.core.collection.ListUtil;  
4 -import cn.hutool.core.util.ArrayUtil;  
5 -import cn.iocoder.yudao.framework.common.core.IntArrayValuable;  
6 -import lombok.AllArgsConstructor;  
7 -import lombok.Getter;  
8 -  
9 -import java.util.Arrays;  
10 -import java.util.List;  
11 -  
12 -/**  
13 - * 社交平台的类型枚举  
14 - *  
15 - * @author 芋道源码  
16 - */  
17 -@Getter  
18 -@AllArgsConstructor  
19 -public enum SysSocialTypeEnum implements IntArrayValuable {  
20 -  
21 - GITEE(10, "GITEE"), // https://gitee.com/api/v5/oauth_doc#/  
22 - DINGTALK(20, "DINGTALK"), // https://developers.dingtalk.com/document/app/obtain-identity-credentials  
23 - WECHAT_ENTERPRISE(30, "WECHAT_ENTERPRISE"), // https://xkcoding.com/2019/08/06/use-justauth-integration-wechat-enterprise.html  
24 - ;  
25 -  
26 - public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(SysSocialTypeEnum::getType).toArray();  
27 -  
28 - public static final List<Integer> WECHAT_ALL = ListUtil.toList(WECHAT_ENTERPRISE.type);  
29 -  
30 - /**  
31 - * 类型  
32 - */  
33 - private final Integer type;  
34 - /**  
35 - * 类型的标识  
36 - */  
37 - private final String source;  
38 -  
39 - @Override  
40 - public int[] array() {  
41 - return ARRAYS;  
42 - }  
43 -  
44 - public static SysSocialTypeEnum valueOfType(Integer type) {  
45 - return ArrayUtil.firstMatch(o -> o.getType().equals(type), values());  
46 - }  
47 -  
48 - public static List<Integer> getRelationTypes(Integer type) {  
49 - if (WECHAT_ALL.contains(type)) {  
50 - return WECHAT_ALL;  
51 - }  
52 - return ListUtil.toList(type);  
53 - }  
54 -  
55 -}  
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/SysAuthController.java
1 package cn.iocoder.yudao.userserver.modules.system.controller.auth; 1 package cn.iocoder.yudao.userserver.modules.system.controller.auth;
2 2
  3 +import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialService;
  4 +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
3 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 5 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.*; 6 import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.*;
5 import cn.iocoder.yudao.userserver.modules.system.service.auth.SysAuthService; 7 import cn.iocoder.yudao.userserver.modules.system.service.auth.SysAuthService;
6 import cn.iocoder.yudao.userserver.modules.system.service.sms.SysSmsCodeService; 8 import cn.iocoder.yudao.userserver.modules.system.service.sms.SysSmsCodeService;
  9 +import com.alibaba.fastjson.JSON;
7 import io.swagger.annotations.Api; 10 import io.swagger.annotations.Api;
8 import io.swagger.annotations.ApiImplicitParam; 11 import io.swagger.annotations.ApiImplicitParam;
9 import io.swagger.annotations.ApiImplicitParams; 12 import io.swagger.annotations.ApiImplicitParams;
@@ -13,11 +16,13 @@ import org.springframework.validation.annotation.Validated; @@ -13,11 +16,13 @@ import org.springframework.validation.annotation.Validated;
13 import org.springframework.web.bind.annotation.*; 16 import org.springframework.web.bind.annotation.*;
14 17
15 import javax.annotation.Resource; 18 import javax.annotation.Resource;
  19 +import javax.servlet.http.HttpServletRequest;
16 import javax.validation.Valid; 20 import javax.validation.Valid;
17 21
18 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 22 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
19 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; 23 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
20 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getUserAgent; 24 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getUserAgent;
  25 +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
21 26
22 @Api(tags = "认证") 27 @Api(tags = "认证")
23 @RestController 28 @RestController
@@ -30,6 +35,9 @@ public class SysAuthController { @@ -30,6 +35,9 @@ public class SysAuthController {
30 private SysAuthService authService; 35 private SysAuthService authService;
31 @Resource 36 @Resource
32 private SysSmsCodeService smsCodeService; 37 private SysSmsCodeService smsCodeService;
  38 + @Resource
  39 + private SysSocialService socialService;
  40 +
33 41
34 @PostMapping("/login") 42 @PostMapping("/login")
35 @ApiOperation("使用手机 + 密码登录") 43 @ApiOperation("使用手机 + 密码登录")
@@ -70,42 +78,51 @@ public class SysAuthController { @@ -70,42 +78,51 @@ public class SysAuthController {
70 }) 78 })
71 public CommonResult<String> socialAuthRedirect(@RequestParam("type") Integer type, 79 public CommonResult<String> socialAuthRedirect(@RequestParam("type") Integer type,
72 @RequestParam("redirectUri") String redirectUri) { 80 @RequestParam("redirectUri") String redirectUri) {
73 -// return CommonResult.success(socialService.getAuthorizeUrl(type, redirectUri));  
74 - return null; 81 + return CommonResult.success(socialService.getAuthorizeUrl(type, redirectUri));
  82 + }
  83 +
  84 + // TODO @timfruit:这个接口,是要删除的么?
  85 + @GetMapping("/social-login-get")
  86 + @ApiOperation("微信公众号授权回调地址,输出social-login2的必要参数用于测试,使用 code 授权码")
  87 + @ResponseBody
  88 + @Deprecated
  89 + public CommonResult<MbrAuthSocialLoginReqVO> socialLoginGet(HttpServletRequest request,String code,String state) {
  90 + // 返回结果
  91 + MbrAuthSocialLoginReqVO reqVO = MbrAuthSocialLoginReqVO.builder().state(state).code(code).build();
  92 + reqVO.setType(12);
  93 + //输出social-login2的必要参数用于测试
  94 + System.out.println(JSON.toJSON(reqVO));
  95 + return success(reqVO);
75 } 96 }
76 97
77 @PostMapping("/social-login") 98 @PostMapping("/social-login")
78 @ApiOperation("社交登录,使用 code 授权码") 99 @ApiOperation("社交登录,使用 code 授权码")
79 - public CommonResult<SysAuthLoginRespVO> socialLogin(@RequestBody @Valid MbrAuthSocialLoginReqVO reqVO) {  
80 -// String token = authService.socialLogin(reqVO, getClientIP(), getUserAgent());  
81 -// // 返回结果  
82 -// return success(MbrAuthLoginRespVO.builder().token(token).build());  
83 - return null; 100 + public CommonResult<SysAuthLoginRespVO> socialLogin(@RequestBody @Valid MbrAuthSocialLoginReqVO reqVO) {
  101 + String token = authService.socialLogin(reqVO, getClientIP(), getUserAgent());
  102 + return success(SysAuthLoginRespVO.builder().token(token).build());
84 } 103 }
85 104
  105 + // TODO @timfruit:社交登陆时,使用手机验证码来验证哈。这块我当时没设计好,改改,嘿嘿。
  106 +
86 @PostMapping("/social-login2") 107 @PostMapping("/social-login2")
87 @ApiOperation("社交登录,使用 code 授权码 + 账号密码") 108 @ApiOperation("社交登录,使用 code 授权码 + 账号密码")
88 public CommonResult<SysAuthLoginRespVO> socialLogin2(@RequestBody @Valid MbrAuthSocialLogin2ReqVO reqVO) { 109 public CommonResult<SysAuthLoginRespVO> socialLogin2(@RequestBody @Valid MbrAuthSocialLogin2ReqVO reqVO) {
89 -// String token = authService.socialLogin2(reqVO, getClientIP(), getUserAgent());  
90 -// // 返回结果  
91 -// return success(MbrAuthLoginRespVO.builder().token(token).build());  
92 - return null; 110 + String token = authService.socialLogin2(reqVO, getClientIP(), getUserAgent());
  111 + return success(SysAuthLoginRespVO.builder().token(token).build());
93 } 112 }
94 113
95 @PostMapping("/social-bind") 114 @PostMapping("/social-bind")
96 @ApiOperation("社交绑定,使用 code 授权码") 115 @ApiOperation("社交绑定,使用 code 授权码")
97 public CommonResult<Boolean> socialBind(@RequestBody @Valid MbrAuthSocialBindReqVO reqVO) { 116 public CommonResult<Boolean> socialBind(@RequestBody @Valid MbrAuthSocialBindReqVO reqVO) {
98 -// authService.socialBind(getLoginUserId(), reqVO);  
99 -// return CommonResult.success(true);  
100 - return null; 117 + authService.socialBind(getLoginUserId(), reqVO);
  118 + return CommonResult.success(true);
101 } 119 }
102 120
103 @DeleteMapping("/social-unbind") 121 @DeleteMapping("/social-unbind")
104 @ApiOperation("取消社交绑定") 122 @ApiOperation("取消社交绑定")
105 public CommonResult<Boolean> socialUnbind(@RequestBody MbrAuthSocialUnbindReqVO reqVO) { 123 public CommonResult<Boolean> socialUnbind(@RequestBody MbrAuthSocialUnbindReqVO reqVO) {
106 -// socialService.unbindSocialUser(getLoginUserId(), reqVO.getType(), reqVO.getUnionId());  
107 -// return CommonResult.success(true);  
108 - return null; 124 + socialService.unbindSocialUser(getLoginUserId(), reqVO.getType(), reqVO.getUnionId(), UserTypeEnum.MEMBER);
  125 + return CommonResult.success(true);
109 } 126 }
110 127
111 } 128 }
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthSocialBindReqVO.java
1 package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo; 1 package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo;
2 2
  3 +import cn.iocoder.yudao.coreservice.modules.system.enums.social.SysSocialTypeEnum;
3 import cn.iocoder.yudao.framework.common.validation.InEnum; 4 import cn.iocoder.yudao.framework.common.validation.InEnum;
4 -import cn.iocoder.yudao.userserver.modules.member.enums.social.SysSocialTypeEnum;  
5 import io.swagger.annotations.ApiModel; 5 import io.swagger.annotations.ApiModel;
6 import io.swagger.annotations.ApiModelProperty; 6 import io.swagger.annotations.ApiModelProperty;
7 import lombok.AllArgsConstructor; 7 import lombok.AllArgsConstructor;
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthSocialLogin2ReqVO.java
1 package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo; 1 package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo;
2 2
  3 +import cn.iocoder.yudao.coreservice.modules.system.enums.social.SysSocialTypeEnum;
3 import cn.iocoder.yudao.framework.common.validation.InEnum; 4 import cn.iocoder.yudao.framework.common.validation.InEnum;
4 -import cn.iocoder.yudao.userserver.modules.member.enums.social.SysSocialTypeEnum;  
5 import io.swagger.annotations.ApiModel; 5 import io.swagger.annotations.ApiModel;
6 import io.swagger.annotations.ApiModelProperty; 6 import io.swagger.annotations.ApiModelProperty;
7 import lombok.AllArgsConstructor; 7 import lombok.AllArgsConstructor;
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthSocialLoginReqVO.java
1 package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo; 1 package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo;
2 2
  3 +import cn.iocoder.yudao.coreservice.modules.system.enums.social.SysSocialTypeEnum;
3 import cn.iocoder.yudao.framework.common.validation.InEnum; 4 import cn.iocoder.yudao.framework.common.validation.InEnum;
4 -import cn.iocoder.yudao.userserver.modules.member.enums.social.SysSocialTypeEnum;  
5 import io.swagger.annotations.ApiModel; 5 import io.swagger.annotations.ApiModel;
6 import io.swagger.annotations.ApiModelProperty; 6 import io.swagger.annotations.ApiModelProperty;
7 import lombok.AllArgsConstructor; 7 import lombok.AllArgsConstructor;
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthSocialUnbindReqVO.java
1 package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo; 1 package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo;
2 2
  3 +import cn.iocoder.yudao.coreservice.modules.system.enums.social.SysSocialTypeEnum;
3 import cn.iocoder.yudao.framework.common.validation.InEnum; 4 import cn.iocoder.yudao.framework.common.validation.InEnum;
4 -import cn.iocoder.yudao.userserver.modules.member.enums.social.SysSocialTypeEnum;  
5 import io.swagger.annotations.ApiModel; 5 import io.swagger.annotations.ApiModel;
6 import io.swagger.annotations.ApiModelProperty; 6 import io.swagger.annotations.ApiModelProperty;
7 import lombok.AllArgsConstructor; 7 import lombok.AllArgsConstructor;
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/enums/SysErrorCodeConstants.java
@@ -14,6 +14,7 @@ public interface SysErrorCodeConstants { @@ -14,6 +14,7 @@ public interface SysErrorCodeConstants {
14 ErrorCode AUTH_LOGIN_USER_DISABLED = new ErrorCode(1005000001, "登录失败,账号被禁用"); 14 ErrorCode AUTH_LOGIN_USER_DISABLED = new ErrorCode(1005000001, "登录失败,账号被禁用");
15 ErrorCode AUTH_LOGIN_FAIL_UNKNOWN = new ErrorCode(1005000002, "登录失败"); // 登录失败的兜底,未知原因 15 ErrorCode AUTH_LOGIN_FAIL_UNKNOWN = new ErrorCode(1005000002, "登录失败"); // 登录失败的兜底,未知原因
16 ErrorCode AUTH_TOKEN_EXPIRED = new ErrorCode(1005000003, "Token 已经过期"); 16 ErrorCode AUTH_TOKEN_EXPIRED = new ErrorCode(1005000003, "Token 已经过期");
  17 + ErrorCode AUTH_THIRD_LOGIN_NOT_BIND = new ErrorCode(1005000004, "未绑定账号,需要进行绑定");
17 18
18 // ========== SMS CODE 模块 1005001000 ========== 19 // ========== SMS CODE 模块 1005001000 ==========
19 ErrorCode USER_SMS_CODE_NOT_FOUND = new ErrorCode(1005001000, "验证码不存在"); 20 ErrorCode USER_SMS_CODE_NOT_FOUND = new ErrorCode(1005001000, "验证码不存在");
@@ -22,4 +23,7 @@ public interface SysErrorCodeConstants { @@ -22,4 +23,7 @@ public interface SysErrorCodeConstants {
22 ErrorCode USER_SMS_CODE_NOT_CORRECT = new ErrorCode(1005001003, "验证码不正确"); 23 ErrorCode USER_SMS_CODE_NOT_CORRECT = new ErrorCode(1005001003, "验证码不正确");
23 ErrorCode USER_SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY = new ErrorCode(1005001004, "超过每日短信发送数量"); 24 ErrorCode USER_SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY = new ErrorCode(1005001004, "超过每日短信发送数量");
24 ErrorCode USER_SMS_CODE_SEND_TOO_FAST = new ErrorCode(1005001005, "短信发送过于频率"); 25 ErrorCode USER_SMS_CODE_SEND_TOO_FAST = new ErrorCode(1005001005, "短信发送过于频率");
  26 +
  27 + // ========== 用户模块 1005002000 ==========
  28 + ErrorCode USER_NOT_EXISTS = new ErrorCode(1005002001, "用户不存在");
25 } 29 }
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/auth/SysAuthService.java
1 package cn.iocoder.yudao.userserver.modules.system.service.auth; 1 package cn.iocoder.yudao.userserver.modules.system.service.auth;
2 2
3 import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService; 3 import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService;
4 -import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.SysAuthLoginReqVO;  
5 -import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.SysAuthSmsLoginReqVO; 4 +import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.*;
6 5
7 import javax.validation.Valid; 6 import javax.validation.Valid;
8 7
@@ -35,4 +34,33 @@ public interface SysAuthService extends SecurityAuthFrameworkService { @@ -35,4 +34,33 @@ public interface SysAuthService extends SecurityAuthFrameworkService {
35 */ 34 */
36 String smsLogin(@Valid SysAuthSmsLoginReqVO reqVO, String userIp, String userAgent); 35 String smsLogin(@Valid SysAuthSmsLoginReqVO reqVO, String userIp, String userAgent);
37 36
  37 +
  38 + /**
  39 + * 社交登录,使用 code 授权码
  40 + *
  41 + * @param reqVO 登录信息
  42 + * @param userIp 用户 IP
  43 + * @param userAgent 用户 UA
  44 + * @return 身份令牌,使用 JWT 方式
  45 + */
  46 + String socialLogin(@Valid MbrAuthSocialLoginReqVO reqVO, String userIp, String userAgent);
  47 +
  48 + /**
  49 + * 社交登录,使用 code 授权码 + 账号密码
  50 + *
  51 + * @param reqVO 登录信息
  52 + * @param userIp 用户 IP
  53 + * @param userAgent 用户 UA
  54 + * @return 身份令牌,使用 JWT 方式
  55 + */
  56 + String socialLogin2(@Valid MbrAuthSocialLogin2ReqVO reqVO, String userIp, String userAgent);
  57 +
  58 + /**
  59 + * 社交绑定,使用 code 授权码
  60 + *
  61 + * @param userId 用户编号
  62 + * @param reqVO 绑定信息
  63 + */
  64 + void socialBind(Long userId, @Valid MbrAuthSocialBindReqVO reqVO);
  65 +
38 } 66 }
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/auth/impl/SysAuthServiceImpl.java
1 package cn.iocoder.yudao.userserver.modules.system.service.auth.impl; 1 package cn.iocoder.yudao.userserver.modules.system.service.auth.impl;
2 2
  3 +import cn.hutool.core.collection.CollUtil;
3 import cn.hutool.core.lang.Assert; 4 import cn.hutool.core.lang.Assert;
4 import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO; 5 import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO;
  6 +import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.social.SysSocialUserDO;
5 import cn.iocoder.yudao.coreservice.modules.system.enums.logger.SysLoginLogTypeEnum; 7 import cn.iocoder.yudao.coreservice.modules.system.enums.logger.SysLoginLogTypeEnum;
6 import cn.iocoder.yudao.coreservice.modules.system.enums.logger.SysLoginResultEnum; 8 import cn.iocoder.yudao.coreservice.modules.system.enums.logger.SysLoginResultEnum;
7 import cn.iocoder.yudao.coreservice.modules.system.service.auth.SysUserSessionCoreService; 9 import cn.iocoder.yudao.coreservice.modules.system.service.auth.SysUserSessionCoreService;
8 import cn.iocoder.yudao.coreservice.modules.system.service.logger.SysLoginLogCoreService; 10 import cn.iocoder.yudao.coreservice.modules.system.service.logger.SysLoginLogCoreService;
9 import cn.iocoder.yudao.coreservice.modules.system.service.logger.dto.SysLoginLogCreateReqDTO; 11 import cn.iocoder.yudao.coreservice.modules.system.service.logger.dto.SysLoginLogCreateReqDTO;
  12 +import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialService;
10 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 13 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
11 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; 14 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
12 import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; 15 import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
13 import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; 16 import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
14 import cn.iocoder.yudao.framework.security.core.LoginUser; 17 import cn.iocoder.yudao.framework.security.core.LoginUser;
15 import cn.iocoder.yudao.userserver.modules.member.service.user.MbrUserService; 18 import cn.iocoder.yudao.userserver.modules.member.service.user.MbrUserService;
16 -import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.SysAuthLoginReqVO;  
17 -import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.SysAuthSmsLoginReqVO; 19 +import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.*;
18 import cn.iocoder.yudao.userserver.modules.system.convert.auth.SysAuthConvert; 20 import cn.iocoder.yudao.userserver.modules.system.convert.auth.SysAuthConvert;
19 import cn.iocoder.yudao.userserver.modules.system.enums.sms.SysSmsSceneEnum; 21 import cn.iocoder.yudao.userserver.modules.system.enums.sms.SysSmsSceneEnum;
20 import cn.iocoder.yudao.userserver.modules.system.service.auth.SysAuthService; 22 import cn.iocoder.yudao.userserver.modules.system.service.auth.SysAuthService;
21 import cn.iocoder.yudao.userserver.modules.system.service.sms.SysSmsCodeService; 23 import cn.iocoder.yudao.userserver.modules.system.service.sms.SysSmsCodeService;
22 import lombok.extern.slf4j.Slf4j; 24 import lombok.extern.slf4j.Slf4j;
  25 +import me.zhyd.oauth.model.AuthUser;
23 import org.springframework.context.annotation.Lazy; 26 import org.springframework.context.annotation.Lazy;
24 import org.springframework.security.authentication.AuthenticationManager; 27 import org.springframework.security.authentication.AuthenticationManager;
25 import org.springframework.security.authentication.BadCredentialsException; 28 import org.springframework.security.authentication.BadCredentialsException;
@@ -33,6 +36,7 @@ import org.springframework.stereotype.Service; @@ -33,6 +36,7 @@ import org.springframework.stereotype.Service;
33 import org.springframework.transaction.annotation.Transactional; 36 import org.springframework.transaction.annotation.Transactional;
34 37
35 import javax.annotation.Resource; 38 import javax.annotation.Resource;
  39 +import java.util.List;
36 import java.util.Objects; 40 import java.util.Objects;
37 41
38 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 42 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -59,6 +63,9 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -59,6 +63,9 @@ public class SysAuthServiceImpl implements SysAuthService {
59 private SysLoginLogCoreService loginLogCoreService; 63 private SysLoginLogCoreService loginLogCoreService;
60 @Resource 64 @Resource
61 private SysUserSessionCoreService userSessionCoreService; 65 private SysUserSessionCoreService userSessionCoreService;
  66 + @Resource
  67 + private SysSocialService socialService;
  68 + private static final UserTypeEnum userTypeEnum = UserTypeEnum.MEMBER;
62 69
63 @Override 70 @Override
64 public UserDetails loadUserByUsername(String mobile) throws UsernameNotFoundException { 71 public UserDetails loadUserByUsername(String mobile) throws UsernameNotFoundException {
@@ -99,6 +106,63 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -99,6 +106,63 @@ public class SysAuthServiceImpl implements SysAuthService {
99 return userSessionCoreService.createUserSession(loginUser, userIp, userAgent); 106 return userSessionCoreService.createUserSession(loginUser, userIp, userAgent);
100 } 107 }
101 108
  109 + @Override
  110 + public String socialLogin(MbrAuthSocialLoginReqVO reqVO, String userIp, String userAgent) {
  111 + // 使用 code 授权码,进行登录
  112 + AuthUser authUser = socialService.getAuthUser(reqVO.getType(), reqVO.getCode(), reqVO.getState());
  113 + org.springframework.util.Assert.notNull(authUser, "授权用户不为空");
  114 +
  115 + // 如果未绑定 SysSocialUserDO 用户,则无法自动登录,进行报错
  116 + String unionId = socialService.getAuthUserUnionId(authUser);
  117 + List<SysSocialUserDO> socialUsers = socialService.getAllSocialUserList(reqVO.getType(), unionId, userTypeEnum);
  118 + if (CollUtil.isEmpty(socialUsers)) {
  119 + throw exception(AUTH_THIRD_LOGIN_NOT_BIND);
  120 + }
  121 +
  122 + // 自动登录
  123 + MbrUserDO user = userService.getUser(socialUsers.get(0).getUserId());
  124 + if (user == null) {
  125 + throw exception(USER_NOT_EXISTS);
  126 + }
  127 + this.createLoginLog(user.getMobile(), SysLoginLogTypeEnum.LOGIN_SOCIAL, SysLoginResultEnum.SUCCESS);
  128 +
  129 + // 创建 LoginUser 对象
  130 + LoginUser loginUser = SysAuthConvert.INSTANCE.convert(user);
  131 +
  132 + // 绑定社交用户(更新)
  133 + socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser, userTypeEnum);
  134 +
  135 + // 缓存登录用户到 Redis 中,返回 sessionId 编号
  136 + return userSessionCoreService.createUserSession(loginUser, userIp, userAgent);
  137 + }
  138 +
  139 + @Override
  140 + public String socialLogin2(MbrAuthSocialLogin2ReqVO reqVO, String userIp, String userAgent) {
  141 + // 使用 code 授权码,进行登录
  142 + AuthUser authUser = socialService.getAuthUser(reqVO.getType(), reqVO.getCode(), reqVO.getState());
  143 + org.springframework.util.Assert.notNull(authUser, "授权用户不为空");
  144 +
  145 + // 使用账号密码,进行登录。
  146 + LoginUser loginUser = this.login0(reqVO.getUsername(), reqVO.getPassword());
  147 +// loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表
  148 +
  149 + // 绑定社交用户(新增)
  150 + socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser, userTypeEnum);
  151 +
  152 + // 缓存登录用户到 Redis 中,返回 sessionId 编号
  153 + return userSessionCoreService.createUserSession(loginUser, userIp, userAgent);
  154 + }
  155 +
  156 + @Override
  157 + public void socialBind(Long userId, MbrAuthSocialBindReqVO reqVO) {
  158 + // 使用 code 授权码,进行登录
  159 + AuthUser authUser = socialService.getAuthUser(reqVO.getType(), reqVO.getCode(), reqVO.getState());
  160 + org.springframework.util.Assert.notNull(authUser, "授权用户不为空");
  161 +
  162 + // 绑定社交用户(新增)
  163 + socialService.bindSocialUser(userId, reqVO.getType(), authUser, userTypeEnum);
  164 + }
  165 +
102 private LoginUser login0(String username, String password) { 166 private LoginUser login0(String username, String password) {
103 final SysLoginLogTypeEnum logTypeEnum = SysLoginLogTypeEnum.LOGIN_USERNAME; 167 final SysLoginLogTypeEnum logTypeEnum = SysLoginLogTypeEnum.LOGIN_USERNAME;
104 // 用户验证 168 // 用户验证
@@ -207,7 +271,7 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -207,7 +271,7 @@ public class SysAuthServiceImpl implements SysAuthService {
207 reqDTO.setLogType(SysLoginLogTypeEnum.LOGOUT_SELF.getType()); 271 reqDTO.setLogType(SysLoginLogTypeEnum.LOGOUT_SELF.getType());
208 reqDTO.setTraceId(TracerUtils.getTraceId()); 272 reqDTO.setTraceId(TracerUtils.getTraceId());
209 reqDTO.setUserId(userId); 273 reqDTO.setUserId(userId);
210 - reqDTO.setUserType(UserTypeEnum.MEMBER.getValue()); 274 + reqDTO.setUserType(userTypeEnum.getValue());
211 reqDTO.setUsername(username); 275 reqDTO.setUsername(username);
212 reqDTO.setUserAgent(ServletUtils.getUserAgent()); 276 reqDTO.setUserAgent(ServletUtils.getUserAgent());
213 reqDTO.setUserIp(ServletUtils.getClientIP()); 277 reqDTO.setUserIp(ServletUtils.getClientIP());
yudao-user-server/src/main/resources/application-dev.yaml
@@ -141,3 +141,30 @@ yudao: @@ -141,3 +141,30 @@ yudao:
141 pay: 141 pay:
142 pay-notify-url: http://niubi.natapp1.cc/api/pay/order/notify 142 pay-notify-url: http://niubi.natapp1.cc/api/pay/order/notify
143 refund-notify-url: http://niubi.natapp1.cc/api/pay/refund/notify 143 refund-notify-url: http://niubi.natapp1.cc/api/pay/refund/notify
  144 +
  145 +
  146 +justauth:
  147 + enabled: true
  148 + type: # TODO @timfruit:GITEE、DINGTALK、WECHAT_ENTERPRISE 这个几个,对于用户端是不需要的哈,可以删除噢
  149 + GITEE: # Gitee
  150 + client-id: ee61f0374a4c6c404a8717094caa7a410d76950e45ff60348015830c519ba5c1
  151 + client-secret: 7c044a5671be3b051414db0cf2cec6ad702dd298d2416ba24ceaf608e6fa26f9
  152 + ignore-check-redirect-uri: true
  153 + DINGTALK: # 钉钉
  154 + client-id: dingvrnreaje3yqvzhxg
  155 + client-secret: i8E6iZyDvZj51JIb0tYsYfVQYOks9Cq1lgryEjFRqC79P3iJcrxEwT6Qk2QvLrLI
  156 + ignore-check-redirect-uri: true
  157 + WECHAT_ENTERPRISE: # 企业微信
  158 + client-id: wwd411c69a39ad2e54
  159 + client-secret: 1wTb7hYxnpT2TUbIeHGXGo7T0odav1ic10mLdyyATOw
  160 + agent-id: 1000004
  161 + ignore-check-redirect-uri: true
  162 + WECHAT_MP: # 微信公众平台 - H5 https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index
  163 + client-id: wxa5a05b85ac361f96
  164 + client-secret: 247073c7cebb67f27f0e769195c2a57e
  165 + ignore-check-redirect-uri: true
  166 + cache:
  167 + type: REDIS
  168 + prefix: 'social_auth_state:' # 缓存前缀,目前只对 Redis 缓存生效,默认 JUSTAUTH::STATE::
  169 + timeout: 24h # 超时时长,目前只对 Redis 缓存生效,默认 3 分钟
  170 +
yudao-user-server/src/main/resources/application-local.yaml
@@ -155,3 +155,28 @@ yudao: @@ -155,3 +155,28 @@ yudao:
155 pay: 155 pay:
156 pay-notify-url: http://niubi.natapp1.cc/api/pay/order/notify 156 pay-notify-url: http://niubi.natapp1.cc/api/pay/order/notify
157 refund-notify-url: http://niubi.natapp1.cc/api/pay/refund/notify 157 refund-notify-url: http://niubi.natapp1.cc/api/pay/refund/notify
  158 +
  159 +justauth:
  160 + enabled: true
  161 + type:
  162 + WECHAT_MP: # 微信公众平台 - 移动端 H5 https://www.yuque.com/docs/share/a795bef6-ee8a-494a-8dc4-2ef41927743b?#%20%E3%80%8A%E5%BE%AE%E4%BF%A1%E5%85%AC%E4%BC%97%E5%8F%B7%E6%B5%8B%E8%AF%95%E3%80%8B
  163 + client-id: wxa5a05b85ac361f96
  164 + client-secret: 247073c7cebb67f27f0e769195c2a57e
  165 +# client-id: wx5b23ba7a5589ecbb # TODO 芋艿:自己的测试,后续可以删除
  166 +# client-secret: 2a7b3b20c537e52e74afd395eb85f61f
  167 + ignore-check-redirect-uri: true
  168 + extend:
  169 + enum-class: cn.iocoder.yudao.coreservice.modules.system.compent.justauth.AuthExtendSource
  170 + config:
  171 + WECHAT_MINI_PROGRAM: # 微信小程序 https://www.yuque.com/docs/share/88e3d30a-6830-45fc-8c25-dae485aef3aa?#%20%E3%80%8A%E5%B0%8F%E7%A8%8B%E5%BA%8F%E6%8E%88%E6%9D%83%E7%99%BB%E5%BD%95%E3%80%8B
  172 + request-class: cn.iocoder.yudao.coreservice.modules.system.compent.justauth.AuthWeChatMiniProgramRequest
  173 + client-id: wx44d047d87e6284d8
  174 + client-secret: 21c3b7a8a51ee1b8f5cf875848ed4466
  175 +# client-id: wx63c280fe3248a3e7 # TODO 芋艿:自己的测试,后续可以删除
  176 +# client-secret: 6f270509224a7ae1296bbf1c8cb97aed
  177 + ignore-check-redirect-uri: true
  178 + ignore-check-state: true
  179 + cache:
  180 + type: REDIS
  181 + prefix: 'social_auth_state:' # 缓存前缀,目前只对 Redis 缓存生效,默认 JUSTAUTH::STATE::
  182 + timeout: 24h # 超时时长,目前只对 Redis 缓存生效,默认 3 分钟
yudao-user-server/src/main/resources/static/social-login.html 0 → 100644
  1 +<!DOCTYPE html>
  2 +<html>
  3 +<head>
  4 + <meta charset="UTF-8">
  5 + <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"/>
  6 + <title>社交登陆测试页</title>
  7 + <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
  8 +</head>
  9 +<body>
  10 +<div>点击如下按钮,发起登陆的测试</div>
  11 +<div>
  12 + <button id="wx_pub">微信公众号</button>
  13 +</div>
  14 +</body>
  15 +<script>
  16 + let server = 'http://127.0.0.1:28080';
  17 +
  18 + // 微信公众号
  19 + $( "#wx_pub").on( "click", function() {
  20 + // 获得授权链接
  21 + $.ajax({
  22 + url: server + "/api/social-auth-redirect?type=31&redirectUri=" +
  23 + encodeURIComponent(server + '/api/social-login-get'),
  24 + method: 'GET',
  25 + success: function( result ) {
  26 + if (result.code !== 0) {
  27 + alert('获得授权链接失败,原因:' + result.msg)
  28 + return;
  29 + }
  30 + // 跳转重定向
  31 + document.location.href = result.data;
  32 + }
  33 + })
  34 + });
  35 +</script>
  36 +</html>
更新日志.md
@@ -15,6 +15,7 @@ TODO @@ -15,6 +15,7 @@ TODO
15 15
16 * 支付 16 * 支付
17 * 用户前台的社交登陆 17 * 用户前台的社交登陆
  18 +* 用户前台的修改手机、修改密码、忘记密码
18 19
19 ## [v1.1.0] 2021.10.25 20 ## [v1.1.0] 2021.10.25
20 21