1
0
mirror of https://gitee.com/bookshelfplus/bookshelfplus synced 2025-09-09 10:21:38 +08:00
Code Issues Projects Releases Wiki Activity GitHub Gitee

第三方登录回调后登陆系统用户逻辑基本完成

This commit is contained in:
2022-04-04 19:20:07 +08:00
parent 71feaffeb9
commit 54911675a1
20 changed files with 502 additions and 41 deletions

View File

@@ -13,7 +13,11 @@ public enum BusinessErrorCode implements CommonError {
USER_ALREADY_EXIST(20005, "用户已存在"),
// 30000开头为权限相关错误定义
OPERATION_NOT_ALLOWED(30001, "用户没有此操作的权限");
OPERATION_NOT_ALLOWED(30001, "用户没有此操作的权限"),
// 40000开头为第三方登录相关错误定义
THIRD_PARTY_LOGIN_FAIL(40001, "第三方登录失败");
private BusinessErrorCode(int errCode, String errMsg) {

View File

@@ -13,9 +13,9 @@ public class BusinessException extends Exception implements CommonError {
}
// 接收自定义errMsg的方式构造业务异常
public BusinessException(CommonError commonError,String errMsg){
public BusinessException(CommonError commonError, String errMsg) {
super();
this.commonError=commonError;
this.commonError = commonError;
this.commonError.setErrMsg(errMsg);
}

View File

@@ -3,10 +3,13 @@ package plus.bookshelf.Controller.Controller;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import me.zhyd.oauth.config.AuthConfig;
import me.zhyd.oauth.exception.AuthException;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.request.AuthGiteeRequest;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.utils.AuthStateUtils;
import org.apache.tomcat.jni.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@@ -14,6 +17,16 @@ import plus.bookshelf.Common.Error.BusinessErrorCode;
import plus.bookshelf.Common.Error.BusinessException;
import plus.bookshelf.Common.Response.CommonReturnType;
import plus.bookshelf.Common.ThirdParty.ThirdPartyConfig;
import plus.bookshelf.Controller.VO.UserVO;
import plus.bookshelf.Dao.DO.ThirdPartyUserAuthDO;
import plus.bookshelf.Dao.DO.ThirdPartyUserDO;
import plus.bookshelf.Dao.Mapper.ThirdPartyUserAuthDOMapper;
import plus.bookshelf.Dao.Mapper.ThirdPartyUserDOMapper;
import plus.bookshelf.Service.Impl.ThirdPartyUserServiceImpl;
import plus.bookshelf.Service.Model.UserModel;
import java.util.Map;
import java.util.Objects;
@Api(tags = "第三方登录")
@Controller
@@ -28,6 +41,9 @@ public class ThirdPartyController extends BaseController {
@Autowired
private ThirdPartyConfig thirdPartyConfig;
@Autowired
ThirdPartyUserServiceImpl thirdPartyUserService;
@ApiOperation(value = "第三方用户登录跳转地址", notes = "传入需要登录的第三方平台大小写均可返回跳转url")
@RequestMapping(value = "login", method = {RequestMethod.GET})
@ResponseBody
@@ -40,15 +56,26 @@ public class ThirdPartyController extends BaseController {
@ApiOperation(value = "快捷登录回调函数", notes = "传入 code 值,进行登录")
@RequestMapping(value = "callback/{platform}", method = {RequestMethod.GET})
@ResponseBody
public CommonReturnType qq(@PathVariable("platform") String platform,
// @RequestParam Map<String,String> params,
AuthCallback callback) throws BusinessException {
// System.out.println(params);
// System.out.println(platform);
// System.out.println(params.get("code"));
// System.out.println(params.get("state"));
public CommonReturnType callback(@PathVariable("platform") String platform,
// @RequestParam Map<String,String> params,
AuthCallback callback) throws BusinessException {
AuthRequest authRequest = getAuthRequest(platform);
return CommonReturnType.create(authRequest.login(callback));
AuthResponse authResponse;
try {
authResponse = authRequest.login(callback);
} catch (AuthException e) {
// [ERROR] - Failed to login with oauth authorization.
throw new BusinessException(BusinessErrorCode.THIRD_PARTY_LOGIN_FAIL, "第三方登录失败");
}
UserModel userModel = thirdPartyUserService.loginCallback(authResponse);
UserVO userVO = UserController.convertFromService(userModel);
if (userModel != null) {
String token = onLogin(userModel);
userVO.setToken(token); // token 仅在用户登录时传一次,后面获取用户状态接口中不重复返回 token 信息
}
return CommonReturnType.create(userVO);
}
// 创建授权request

View File

@@ -91,7 +91,7 @@ public class UserController extends BaseController {
return CommonReturnType.create(userVO);
}
private UserVO convertFromService(UserModel userModel) {
public static UserVO convertFromService(UserModel userModel) {
if (userModel == null) {
return null;
}

View File

@@ -17,7 +17,7 @@ public class ThirdPartyUserAuthDO {
*
* @mbg.generated
*/
private String userId;
private Integer userId;
/**
*
@@ -26,7 +26,7 @@ public class ThirdPartyUserAuthDO {
*
* @mbg.generated
*/
private String thirdPartyUserId;
private Integer thirdPartyUserId;
/**
* This method was generated by MyBatis Generator.
@@ -60,7 +60,7 @@ public class ThirdPartyUserAuthDO {
*
* @mbg.generated
*/
public String getUserId() {
public Integer getUserId() {
return userId;
}
@@ -72,8 +72,8 @@ public class ThirdPartyUserAuthDO {
*
* @mbg.generated
*/
public void setUserId(String userId) {
this.userId = userId == null ? null : userId.trim();
public void setUserId(Integer userId) {
this.userId = userId;
}
/**
@@ -84,7 +84,7 @@ public class ThirdPartyUserAuthDO {
*
* @mbg.generated
*/
public String getThirdPartyUserId() {
public Integer getThirdPartyUserId() {
return thirdPartyUserId;
}
@@ -96,7 +96,7 @@ public class ThirdPartyUserAuthDO {
*
* @mbg.generated
*/
public void setThirdPartyUserId(String thirdPartyUserId) {
this.thirdPartyUserId = thirdPartyUserId == null ? null : thirdPartyUserId.trim();
public void setThirdPartyUserId(Integer thirdPartyUserId) {
this.thirdPartyUserId = thirdPartyUserId;
}
}

View File

@@ -5,6 +5,14 @@ import plus.bookshelf.Dao.DO.ThirdPartyUserAuthDO;
@Repository // 添加这个注解Autowired的时候idea就不会报错了
public interface ThirdPartyUserAuthDOMapper {
/**
* This method was generated by MyBatis Generator.
* This method corresponds to the database table third_party_user_auth_relation
*
* @mbg.generated
*/
int deleteByPrimaryKey(Integer id);
/**
* This method was generated by MyBatis Generator.
* This method corresponds to the database table third_party_user_auth_relation
@@ -20,4 +28,44 @@ public interface ThirdPartyUserAuthDOMapper {
* @mbg.generated
*/
int insertSelective(ThirdPartyUserAuthDO record);
/**
* This method was generated by MyBatis Generator.
* This method corresponds to the database table third_party_user_auth_relation
*
* @mbg.generated
*/
ThirdPartyUserAuthDO selectByPrimaryKey(Integer id);
/**
* This method was generated by MyBatis Generator.
* This method corresponds to the database table third_party_user_auth_relation
*
* @mbg.generated
*/
int updateByPrimaryKeySelective(ThirdPartyUserAuthDO record);
/**
* This method was generated by MyBatis Generator.
* This method corresponds to the database table third_party_user_auth_relation
*
* @mbg.generated
*/
int updateByPrimaryKey(ThirdPartyUserAuthDO record);
/**
* This method was generated by MyBatis Generator.
* This method corresponds to the database table third_party_user_auth_relation
*
* @mbg.generated
*/
ThirdPartyUserAuthDO selectByThirdPartyUserId(Integer id);
/**
* This method was generated by MyBatis Generator.
* This method corresponds to the database table third_party_user_auth_relation
*
* @mbg.generated
*/
ThirdPartyUserAuthDO selectByUserId(Integer id);
}

View File

@@ -1,6 +1,7 @@
package plus.bookshelf.Dao.Mapper;
import org.springframework.stereotype.Repository;
import plus.bookshelf.Dao.DO.ThirdPartyUserAuthDO;
import plus.bookshelf.Dao.DO.ThirdPartyUserDO;
@Repository // 添加这个注解Autowired的时候idea就不会报错了
@@ -52,4 +53,12 @@ public interface ThirdPartyUserDOMapper {
* @mbg.generated
*/
int updateByPrimaryKey(ThirdPartyUserDO record);
/**
* 通过 uuid + source 查询第三方登录的用户信息limit 1
* @param uuid
* @param source
* @return
*/
ThirdPartyUserDO selectByUuidAndSource(String uuid, String source);
}

View File

@@ -0,0 +1,174 @@
package plus.bookshelf.Service.Impl;
import me.zhyd.oauth.enums.AuthUserGender;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthToken;
import me.zhyd.oauth.model.AuthUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import plus.bookshelf.Common.Error.BusinessErrorCode;
import plus.bookshelf.Common.Error.BusinessException;
import plus.bookshelf.Dao.DO.ThirdPartyUserAuthDO;
import plus.bookshelf.Dao.DO.ThirdPartyUserDO;
import plus.bookshelf.Dao.Mapper.ThirdPartyUserAuthDOMapper;
import plus.bookshelf.Dao.Mapper.ThirdPartyUserDOMapper;
import plus.bookshelf.Service.Model.UserModel;
import plus.bookshelf.Service.Service.ThirdPartyUserService;
import java.util.Map;
@Service
public class ThirdPartyUserServiceImpl implements ThirdPartyUserService {
@Autowired
ThirdPartyUserDOMapper thirdPartyUserDOMapper;
@Autowired
ThirdPartyUserAuthDOMapper thirdPartyUserAuthDOMapper;
@Autowired
UserServiceImpl userService;
@Override
@Transactional
public UserModel loginCallback(AuthResponse authResponse) throws BusinessException {
int code = authResponse.getCode();
if (code == 5008) {
// 第三方平台拒绝授权
throw new BusinessException(BusinessErrorCode.PARAMETER_VALIDATION_ERROR, "第三方登录失败,用户已取消第三方登录或第三方平台拒绝授权");
} else if (code == 5009) {
// 授权过期
throw new BusinessException(BusinessErrorCode.PARAMETER_VALIDATION_ERROR, "第三方授权过期,请重新登录");
}
if (code == 2000) {
// 回调成功
// 将回调结果转换为 Data Object
ThirdPartyUserDO currentThirdPartyUserDO = getThirdPartyUserDOFromAuthData(authResponse.getData());
// 根据 uuid + source 唯一确定一个平台的用户 refer: https://justauth.wiki/features/integrate-existing-systems/
String uuid = currentThirdPartyUserDO.getUuid();
String source = currentThirdPartyUserDO.getSource();
ThirdPartyUserDO existThirdPartyUserDO = thirdPartyUserDOMapper.selectByUuidAndSource(uuid, source);
if (existThirdPartyUserDO != null) {
// 之前已经授权登录过
// 更新数据库中的第三方登录信息
currentThirdPartyUserDO.setId(existThirdPartyUserDO.getId());
thirdPartyUserDOMapper.updateByPrimaryKeySelective(currentThirdPartyUserDO);
// 检查第三方账号有无绑定到系统账号
ThirdPartyUserAuthDO thirdPartyUserAuthDO = thirdPartyUserAuthDOMapper.selectByThirdPartyUserId(currentThirdPartyUserDO.getId());
if (thirdPartyUserAuthDO != null) {
// 已经绑定到系统账号
// 取得用户信息,并登录
Integer userId = thirdPartyUserAuthDO.getUserId();
UserModel userModel = userService.getUserById(userId);
return userModel;
} else {
// 未绑定到系统账号
throw new BusinessException(BusinessErrorCode.PARAMETER_VALIDATION_ERROR, "第三方登录失败,该第三方账号未绑定到系统账号,请先绑定");
}
} else {
// 之前未授权登录过
// 将新的用户信息插入到数据库
thirdPartyUserDOMapper.insertSelective(currentThirdPartyUserDO);
throw new BusinessException(BusinessErrorCode.PARAMETER_VALIDATION_ERROR, "第三方登录失败,该第三方账号未绑定到系统账号,请先绑定");
}
} else {
// 未知错误
throw new BusinessException(BusinessErrorCode.UNKNOWN_ERROR, "未知错误,登录失败");
}
}
private ThirdPartyUserDO getThirdPartyUserDOFromAuthData(Object authData) {
AuthUser data = (AuthUser) authData;
String uuid = data.getUuid();
String username = data.getUsername();
String nickname = data.getNickname();
String avatar = data.getAvatar();
String blog = data.getBlog();
String company = data.getCompany();
String location = data.getLocation();
String email = data.getEmail();
String remark = data.getRemark();
AuthUserGender gender = data.getGender();
String source = data.getSource();
AuthToken token = data.getToken();
String accessToken = token.getAccessToken();
int expiresIn = token.getExpireIn();
String refreshToken = token.getRefreshToken();
int refreshTokenExpireIn = token.getRefreshTokenExpireIn();
String uid = token.getUid();
String openId = token.getOpenId();
String accessCode = token.getAccessCode();
String unionId = token.getUnionId();
String scope = token.getScope();
String tokenType = token.getTokenType();
String idToken = token.getIdToken();
String macAlgorithm = token.getMacAlgorithm();
String macKey = token.getMacKey();
String code = token.getCode();
String oauthToken = token.getOauthToken();
String oauthTokenSecret = token.getOauthTokenSecret();
String userId = token.getUserId();
String screenName = token.getScreenName();
String oauthCallbackConfirmed = token.getOauthToken();
// String uuid = data.get("uuid").toString();
// String username = data.get("username").toString();
// String nickname = data.get("nickname").toString();
// String avatar = data.get("avatar").toString();
// String blog = data.get("blog").toString();
// String company = data.get("company").toString();
// String location = data.get("location").toString();
// String email = data.get("email").toString();
// String remark = data.get("remark").toString();
// String gender = data.get("gender").toString();
// String source = data.get("source").toString();
// Map token = (Map) data.get("token");
// String accessToken = token.get("accessToken").toString();
// int expiresIn = Integer.parseInt(token.get("expiresIn").toString());
// String refreshToken = token.get("refreshToken").toString();
// int refreshTokenExpireIn = Integer.parseInt(token.get("refreshTokenExpireIn").toString());
// String uid = token.get("uid").toString();
// String openId = token.get("openId").toString();
// String accessCode = token.get("accessCode").toString();
// String unionId = token.get("unionId").toString();
// String scope = token.get("scope").toString();
// String tokenType = token.get("tokenType").toString();// token 类型,默认为 bearer
// String idToken = token.get("idToken").toString();// id_token
// String macAlgorithm = token.get("macAlgorithm").toString();// mac 算法
// String macKey = token.get("macKey").toString();// mac 密钥
// String code = token.get("code").toString();// code
// String oauthToken = token.get("oauthToken").toString();// oauth_token
// String oauthTokenSecret = token.get("oauthTokenSecret").toString();// oauth_token_secret
// String userId = token.get("userId").toString();// user_id
// String screenName = token.get("screenName").toString();// screen_name
// String oauthCallbackConfirmed = token.get("oauthCallbackConfirmed").toString();// oauth_callback_confirmed
ThirdPartyUserDO thirdPartyUserDO = new ThirdPartyUserDO();
thirdPartyUserDO.setUuid(uuid);
thirdPartyUserDO.setSource(source);
thirdPartyUserDO.setAccessToken(accessToken);
thirdPartyUserDO.setExpireIn(expiresIn);
thirdPartyUserDO.setRefreshToken(refreshToken);
thirdPartyUserDO.setOpenId(openId);
thirdPartyUserDO.setUid(uid);
thirdPartyUserDO.setAccessCode(accessCode);
thirdPartyUserDO.setUnionId(unionId);
thirdPartyUserDO.setScope(scope);
thirdPartyUserDO.setTokenType(tokenType);
thirdPartyUserDO.setIdToken(idToken);
thirdPartyUserDO.setMacAlgorithm(macAlgorithm);
thirdPartyUserDO.setMacKey(macKey);
thirdPartyUserDO.setCode(code);
thirdPartyUserDO.setOauthToken(oauthToken);
thirdPartyUserDO.setOauthTokenSecret(oauthTokenSecret);
return thirdPartyUserDO;
}
}

View File

@@ -8,11 +8,14 @@ import plus.bookshelf.Common.Error.BusinessErrorCode;
import plus.bookshelf.Common.Error.BusinessException;
import plus.bookshelf.Common.SessionManager.RedisSessionManager;
import plus.bookshelf.Controller.VO.UserVO;
import plus.bookshelf.Dao.DO.ThirdPartyUserDO;
import plus.bookshelf.Dao.DO.UserDO;
import plus.bookshelf.Dao.Mapper.UserDOMapper;
import plus.bookshelf.Service.Model.UserModel;
import plus.bookshelf.Service.Service.UserService;
import java.util.Map;
@Service
public class UserServiceImpl implements UserService {

View File

@@ -0,0 +1,13 @@
package plus.bookshelf.Service.Model;
import lombok.Data;
@Data
public class ThirdPartyUserAuthModel {
private Integer id;
private String userId;
private String thirdPartyUserId;
}

View File

@@ -0,0 +1,43 @@
package plus.bookshelf.Service.Model;
import lombok.Data;
@Data
public class ThirdPartyUserModel {
private Integer id;
private String uuid;
private String source;
private String accessToken;
private Integer expireIn;
private String refreshToken;
private String openId;
private String uid;
private String accessCode;
private String unionId;
private String scope;
private String tokenType;
private String idToken;
private String macAlgorithm;
private String macKey;
private String code;
private String oauthToken;
private String oauthTokenSecret;
}

View File

@@ -0,0 +1,18 @@
package plus.bookshelf.Service.Service;
import me.zhyd.oauth.model.AuthResponse;
import org.springframework.transaction.annotation.Transactional;
import plus.bookshelf.Common.Error.BusinessException;
import plus.bookshelf.Service.Model.UserModel;
public interface ThirdPartyUserService {
/**
* 第三方登录完成回调函数
* @param authResponse
* @throws BusinessException
* @return
*/
@Transactional
UserModel loginCallback(AuthResponse authResponse) throws BusinessException;
}