feat(iam): 单点登录
This commit is contained in:
@@ -3,7 +3,6 @@ package com.jero.config;
|
|||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.http.client.ClientHttpRequestFactory;
|
import org.springframework.http.client.ClientHttpRequestFactory;
|
||||||
import org.springframework.http.client.SimpleClientHttpRequestFactory;
|
|
||||||
import org.springframework.web.client.RestTemplate;
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -20,7 +19,11 @@ public class RestTemplateConfig {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
|
public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
|
||||||
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
|
/**
|
||||||
|
* SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
|
||||||
|
*/
|
||||||
|
// 解决https请求证书问题
|
||||||
|
SSL factory = new SSL();
|
||||||
factory.setReadTimeout(5000);//ms
|
factory.setReadTimeout(5000);//ms
|
||||||
factory.setConnectTimeout(15000);//ms
|
factory.setConnectTimeout(15000);//ms
|
||||||
return factory;
|
return factory;
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
package com.jero.config;
|
||||||
|
|
||||||
|
import com.jero.common.exception.JeroBootException;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.http.client.SimpleClientHttpRequestFactory;
|
||||||
|
|
||||||
|
import javax.net.ssl.*;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.security.KeyManagementException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.security.cert.X509Certificate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author nzh
|
||||||
|
* @date 2022/8/22 16:45
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class SSL extends SimpleClientHttpRequestFactory {
|
||||||
|
@Override
|
||||||
|
protected void prepareConnection(HttpURLConnection connection, String httpMethod) throws IOException {
|
||||||
|
if (connection instanceof HttpsURLConnection) {
|
||||||
|
prepareHttpsConnection((HttpsURLConnection) connection);
|
||||||
|
}
|
||||||
|
super.prepareConnection(connection, httpMethod);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void prepareHttpsConnection(HttpsURLConnection connection) {
|
||||||
|
connection.setHostnameVerifier(new SkipHostnameVerifier());
|
||||||
|
try {
|
||||||
|
connection.setSSLSocketFactory(createSslSocketFactory());
|
||||||
|
} catch (Exception ex) {
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private SSLSocketFactory createSslSocketFactory() throws JeroBootException, NoSuchAlgorithmException, KeyManagementException {
|
||||||
|
SSLContext context = SSLContext.getInstance("TLS");
|
||||||
|
context.init(null, new TrustManager[] { new SkipX509TrustManager() }, new SecureRandom());
|
||||||
|
return context.getSocketFactory();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class SkipHostnameVerifier implements HostnameVerifier {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean verify(String s, SSLSession sslSession) {
|
||||||
|
log.info("checkClientTrusted");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SkipX509TrustManager implements X509TrustManager {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public X509Certificate[] getAcceptedIssuers() {
|
||||||
|
return new X509Certificate[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkClientTrusted(X509Certificate[] chain, String authType) {
|
||||||
|
log.info("checkClientTrusted");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkServerTrusted(X509Certificate[] chain, String authType) {
|
||||||
|
log.info("checkServerTrusted");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -76,6 +76,7 @@ public class ShiroConfig {
|
|||||||
filterChainDefinitionMap.put("/sys/checkCaptcha", "anon"); //登录验证码接口排除
|
filterChainDefinitionMap.put("/sys/checkCaptcha", "anon"); //登录验证码接口排除
|
||||||
filterChainDefinitionMap.put("/sys/getRSAPublicKey", "anon"); //获取RSA公钥接口排除
|
filterChainDefinitionMap.put("/sys/getRSAPublicKey", "anon"); //获取RSA公钥接口排除
|
||||||
filterChainDefinitionMap.put("/sys/login", "anon"); //登录接口排除
|
filterChainDefinitionMap.put("/sys/login", "anon"); //登录接口排除
|
||||||
|
filterChainDefinitionMap.put("/iam/loginByOauth2", "anon"); //单点登录接口排除
|
||||||
filterChainDefinitionMap.put("/sys/mLogin", "anon"); //登录接口排除
|
filterChainDefinitionMap.put("/sys/mLogin", "anon"); //登录接口排除
|
||||||
filterChainDefinitionMap.put("/sys/logout", "anon"); //登出接口排除
|
filterChainDefinitionMap.put("/sys/logout", "anon"); //登出接口排除
|
||||||
filterChainDefinitionMap.put("/sys/thirdLogin/**", "anon"); //第三方登录
|
filterChainDefinitionMap.put("/sys/thirdLogin/**", "anon"); //第三方登录
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
package com.jero.modules.system.entity;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: 31318
|
||||||
|
* @Date: 2023/09/26/10:07
|
||||||
|
* @Description:
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Component
|
||||||
|
@ConfigurationProperties(prefix = "oauth")
|
||||||
|
public class Oauth {
|
||||||
|
/**
|
||||||
|
* 客户端应用注册ID
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "客户端应用注册ID")
|
||||||
|
private String clientId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端应用注册密钥
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "客户端应用注册密钥")
|
||||||
|
private String clientSecret;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* authorization_code(4种验证方式(authorization_code,password,refresh_token,client_credentials),采用授权码验证)
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "authorization_code(4种验证方式(authorization_code,password,refresh_token,client_credentials),采用授权码验证)")
|
||||||
|
private String grantType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 必需参数。授权码
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "必需参数。授权码")
|
||||||
|
@NotBlank(message = "授权码不能为空!")
|
||||||
|
private String code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重定向URI
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "重定向URI")
|
||||||
|
@NotBlank(message = "重定向URI不能为空!")
|
||||||
|
private String redirectUri;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过授权码获取token请求地址
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "通过授权码获取token请求地址")
|
||||||
|
private String accessTokenUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过accessToken获取账号信息请求地址
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "通过accessToken获取用户信息请求地址")
|
||||||
|
private String userInfoUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 防止跨站请求伪造(CSRF)标识
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "防止跨站请求伪造(CSRF)标识")
|
||||||
|
private String state;
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
package com.jero.modules.system.entity;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonAlias;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: 31318
|
||||||
|
* @Date: 2023/09/26/10:42
|
||||||
|
* @Description:
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class OauthAccessToken {
|
||||||
|
/** -----------正确响应返回结果----------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 由授权服务器分发的访问令牌
|
||||||
|
*/
|
||||||
|
@JsonAlias("access_token")
|
||||||
|
@ApiModelProperty(value = "由授权服务器分发的访问令牌")
|
||||||
|
private String accessToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 访问令牌生命周期的秒数
|
||||||
|
*/
|
||||||
|
@JsonAlias("expires_in")
|
||||||
|
@ApiModelProperty(value = "访问令牌生命周期的秒数")
|
||||||
|
private String expiresIn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*用来获取新的访问令牌的刷新令牌,使用相同的终端用户访问许可
|
||||||
|
*/
|
||||||
|
@JsonAlias("refresh_token")
|
||||||
|
@ApiModelProperty(value = "可用来获取新的访问令牌的刷新令牌,使用相同的终端用户访问许可")
|
||||||
|
private String refreshToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录用户uid
|
||||||
|
*/
|
||||||
|
@JsonAlias("uid")
|
||||||
|
@ApiModelProperty(value = "登录用户uid")
|
||||||
|
private String uId;
|
||||||
|
|
||||||
|
/** -----------错误响应返回结果----------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 错误码
|
||||||
|
*/
|
||||||
|
@JsonAlias("errcode")
|
||||||
|
@ApiModelProperty(value = "错误码")
|
||||||
|
private String errCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 错误信息
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "错误信息")
|
||||||
|
private String msg;
|
||||||
|
}
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
package com.jero.modules.system.entity;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonAlias;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: 31318
|
||||||
|
* @Date: 2023/09/26/11:14
|
||||||
|
* @Description:
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class OauthUserInfo {
|
||||||
|
/** -----------正确响应返回结果----------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 邮箱
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "邮箱")
|
||||||
|
private String mail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 性别
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "性别")
|
||||||
|
private Integer gender;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "")
|
||||||
|
private String loginType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 名称
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "名称")
|
||||||
|
private String displayName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "")
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 账号名
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "账号名")
|
||||||
|
private List<String> spRoleList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 联系方式
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "联系方式")
|
||||||
|
private String mobile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "")
|
||||||
|
private List<String> spNameList;
|
||||||
|
|
||||||
|
/** -----------错误响应返回结果----------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 错误码
|
||||||
|
*/
|
||||||
|
@JsonAlias("errcode")
|
||||||
|
@ApiModelProperty(value = "错误码")
|
||||||
|
private String errCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 错误信息
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "错误信息")
|
||||||
|
private String msg;
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ package com.jero.modules.system.service;
|
|||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.jero.common.api.vo.Result;
|
import com.jero.common.api.vo.Result;
|
||||||
|
import com.jero.modules.system.entity.Oauth;
|
||||||
import com.jero.modules.system.entity.SysUser;
|
import com.jero.modules.system.entity.SysUser;
|
||||||
import com.jero.modules.system.model.SysLoginModel;
|
import com.jero.modules.system.model.SysLoginModel;
|
||||||
import org.apache.poi.ss.formula.functions.T;
|
import org.apache.poi.ss.formula.functions.T;
|
||||||
@@ -27,6 +28,13 @@ public interface ILoginService{
|
|||||||
*/
|
*/
|
||||||
public Result<JSONObject> login(SysLoginModel sysLoginModel);
|
public Result<JSONObject> login(SysLoginModel sysLoginModel);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param oauth
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Result<JSONObject> loginByOauth2(Oauth oauth);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 退出登录
|
* 退出登录
|
||||||
* @param request response
|
* @param request response
|
||||||
|
|||||||
+130
-3
@@ -1,14 +1,15 @@
|
|||||||
package com.jero.modules.system.service.impl;
|
package com.jero.modules.system.service.impl;
|
||||||
|
|
||||||
import cn.hutool.core.util.RandomUtil;
|
import cn.hutool.core.util.RandomUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
|
||||||
import cn.hutool.crypto.asymmetric.RSA;
|
import cn.hutool.crypto.asymmetric.RSA;
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.aliyuncs.exceptions.ClientException;
|
import com.aliyuncs.exceptions.ClientException;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.jero.common.api.vo.Result;
|
import com.jero.common.api.vo.Result;
|
||||||
import com.jero.common.constant.CacheConstant;
|
import com.jero.common.constant.CacheConstant;
|
||||||
import com.jero.common.constant.CommonConstant;
|
import com.jero.common.constant.CommonConstant;
|
||||||
|
import com.jero.common.exception.JeroBootException;
|
||||||
import com.jero.common.system.api.ISysBaseAPI;
|
import com.jero.common.system.api.ISysBaseAPI;
|
||||||
import com.jero.common.system.util.JwtUtil;
|
import com.jero.common.system.util.JwtUtil;
|
||||||
import com.jero.common.system.vo.LoginUser;
|
import com.jero.common.system.vo.LoginUser;
|
||||||
@@ -25,12 +26,16 @@ import org.apache.commons.lang3.StringUtils;
|
|||||||
import org.apache.poi.ss.formula.functions.T;
|
import org.apache.poi.ss.formula.functions.T;
|
||||||
import org.apache.shiro.SecurityUtils;
|
import org.apache.shiro.SecurityUtils;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.beans.BeanWrapper;
|
||||||
|
import org.springframework.beans.BeanWrapperImpl;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.beans.PropertyDescriptor;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@@ -63,7 +68,10 @@ public class LoginServiceImpl implements ILoginService {
|
|||||||
private ISysUserRoleService sysUserRoleService;
|
private ISysUserRoleService sysUserRoleService;
|
||||||
@Resource
|
@Resource
|
||||||
private ISysRoleService sysRoleService;
|
private ISysRoleService sysRoleService;
|
||||||
|
@Autowired
|
||||||
|
private Oauth oauth;
|
||||||
|
@Autowired
|
||||||
|
private RestTemplate restTemplate;
|
||||||
private static final String BASE_CHECK_CODES = "qwertyuiplkjhgfdsazxcvbnmQWERTYUPLKJHGFDSAZXCVBNM1234567890";
|
private static final String BASE_CHECK_CODES = "qwertyuiplkjhgfdsazxcvbnmQWERTYUPLKJHGFDSAZXCVBNM1234567890";
|
||||||
//密码登录错误的次数前缀
|
//密码登录错误的次数前缀
|
||||||
public static final String RETRY_LOGIN_PREFIX = "login:retryLoginCount_";
|
public static final String RETRY_LOGIN_PREFIX = "login:retryLoginCount_";
|
||||||
@@ -73,6 +81,7 @@ public class LoginServiceImpl implements ILoginService {
|
|||||||
private static final String UTF_8 = "utf-8";
|
private static final String UTF_8 = "utf-8";
|
||||||
private static final String USER_NAME = "用户名: ";
|
private static final String USER_NAME = "用户名: ";
|
||||||
private static final String USER_INFO = "userInfo";
|
private static final String USER_INFO = "userInfo";
|
||||||
|
private static final String LOGIN_SUCCEED = ",登录成功!";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Result<JSONObject> login(SysLoginModel sysLoginModel) {
|
public Result<JSONObject> login(SysLoginModel sysLoginModel) {
|
||||||
@@ -146,12 +155,130 @@ public class LoginServiceImpl implements ILoginService {
|
|||||||
//update-begin--Author:wangshuai Date:20200714 for:登录日志没有记录人员
|
//update-begin--Author:wangshuai Date:20200714 for:登录日志没有记录人员
|
||||||
LoginUser loginUser = new LoginUser();
|
LoginUser loginUser = new LoginUser();
|
||||||
BeanUtils.copyProperties(sysUser, loginUser);
|
BeanUtils.copyProperties(sysUser, loginUser);
|
||||||
baseCommonService.addLog(USER_NAME + username + ",登录成功!", CommonConstant.LOG_TYPE_1, null,loginUser);
|
baseCommonService.addLog(USER_NAME + username + LOGIN_SUCCEED, CommonConstant.LOG_TYPE_1, null,loginUser);
|
||||||
//update-end--Author:wangshuai Date:20200714 for:登录日志没有记录人员
|
//update-end--Author:wangshuai Date:20200714 for:登录日志没有记录人员
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Result<JSONObject> loginByOauth2(Oauth oauth) {
|
||||||
|
Result<JSONObject> result;
|
||||||
|
BeanUtils.copyProperties(this.oauth, oauth, getNullPropertyNames(this.oauth));
|
||||||
|
OauthAccessToken oauthAccessToken;
|
||||||
|
try {
|
||||||
|
// 通过授权码获取accessToken
|
||||||
|
oauthAccessToken = getAccessToken(oauth);
|
||||||
|
}catch (Exception e){
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return Result.error("获取accessToken失败!");
|
||||||
|
}
|
||||||
|
|
||||||
|
OauthUserInfo oauthUserInfo;
|
||||||
|
try {
|
||||||
|
// 通过accessToken获取账号信息
|
||||||
|
oauthUserInfo = getUserInfo(oauth, oauthAccessToken);
|
||||||
|
}catch (Exception e){
|
||||||
|
log.error(e.getMessage());
|
||||||
|
return Result.error("获取账号信息失败!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取用户信息
|
||||||
|
String userName = oauthUserInfo.getSpRoleList().get(0);
|
||||||
|
SysUser sysUser = sysUserService.getUserByName(userName);
|
||||||
|
|
||||||
|
// 校验用户是否有效
|
||||||
|
result = sysUserService.checkUserIsEffective(sysUser);
|
||||||
|
if(!result.isSuccess()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (checkSysPermission(sysUser.getUsername())) {
|
||||||
|
return Result.error("该用户无权限,请联系管理员");
|
||||||
|
}
|
||||||
|
|
||||||
|
//用户登录信息
|
||||||
|
//用户登录信息
|
||||||
|
userInfo(sysUser, result);
|
||||||
|
//update-begin--Author:wangshuai Date:20200714 for:登录日志没有记录人员
|
||||||
|
LoginUser loginUser = new LoginUser();
|
||||||
|
BeanUtils.copyProperties(sysUser, loginUser);
|
||||||
|
baseCommonService.addLog(USER_NAME + userName + LOGIN_SUCCEED, CommonConstant.LOG_TYPE_1, null,loginUser);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private OauthUserInfo getUserInfo(Oauth oauth, OauthAccessToken oauthAccessToken) {
|
||||||
|
String userInfoUrl = oauth.getUserInfoUrl() + "?access_token=" + oauthAccessToken.getAccessToken() + "&client_id=" + oauth.getClientId();
|
||||||
|
/**
|
||||||
|
* 如果返回json
|
||||||
|
* OauthUserInfo oauthUserInfo = restTemplate.getForObject(userInfoUrl, OauthUserInfo.class);
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 返回String --> jsonString --> jsonObject --> 实体
|
||||||
|
String resultStr = restTemplate.getForObject(userInfoUrl, String.class);
|
||||||
|
JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(resultStr));
|
||||||
|
OauthUserInfo oauthUserInfo = JSON.toJavaObject(jsonObject, OauthUserInfo.class);
|
||||||
|
|
||||||
|
if (Objects.isNull(oauthUserInfo) || Objects.isNull(oauthUserInfo.getSpRoleList()) || oauthUserInfo.getSpRoleList().isEmpty()){
|
||||||
|
throw new JeroBootException("获取用户信息返回信息为空!");
|
||||||
|
}
|
||||||
|
if (StringUtils.isBlank(oauthUserInfo.getErrCode())){
|
||||||
|
throw new JeroBootException(oauthUserInfo.getMsg());
|
||||||
|
}
|
||||||
|
return oauthUserInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private OauthAccessToken getAccessToken(Oauth oauth) {
|
||||||
|
/**
|
||||||
|
// 1.表单提交方式
|
||||||
|
// 设置为表单提交,按需求加
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.add("Content-Type","application/x-www-form-urlencoded");
|
||||||
|
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
|
||||||
|
// 组装请求信息
|
||||||
|
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
|
||||||
|
params.add("client_id", oauth.getClientId());
|
||||||
|
params.add("client_secret", oauth.getClientSecret());
|
||||||
|
params.add("grant_type", oauth.getGrantType());
|
||||||
|
params.add("redirect_uri", oauth.getRedirectUri());
|
||||||
|
params.add("code", oauth.getCode());
|
||||||
|
HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(params, headers);
|
||||||
|
OauthAccessToken oauthAccessToken = restTemplate.postForObject(oauth.getAccessTokenUrl(), requestEntity, OauthAccessToken.class);
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 2.params传参
|
||||||
|
String accessTokenUrl = oauth.getAccessTokenUrl();
|
||||||
|
// 拼接参数
|
||||||
|
accessTokenUrl = accessTokenUrl + "?client_id=" + oauth.getClientId()
|
||||||
|
+ "&grant_type=" + oauth.getGrantType()
|
||||||
|
+ "&code=" + oauth.getCode()
|
||||||
|
+ "&client_secret" + oauth.getClientSecret();
|
||||||
|
OauthAccessToken oauthAccessToken = restTemplate.postForObject(accessTokenUrl, null, OauthAccessToken.class);
|
||||||
|
if (Objects.isNull(oauthAccessToken) || StringUtils.isBlank(oauthAccessToken.getAccessToken())){
|
||||||
|
throw new JeroBootException("获取AccessToken返回信息为空!");
|
||||||
|
}
|
||||||
|
if (StringUtils.isBlank(oauthAccessToken.getErrCode())){
|
||||||
|
throw new JeroBootException(oauthAccessToken.getMsg());
|
||||||
|
}
|
||||||
|
return oauthAccessToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解决BeanUtils.copyProperties() 的 null值覆盖问题
|
||||||
|
* @param source
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String[] getNullPropertyNames (Object source) {
|
||||||
|
final BeanWrapper src = new BeanWrapperImpl(source);
|
||||||
|
PropertyDescriptor[] pds = src.getPropertyDescriptors();
|
||||||
|
Set<String> emptyNames = new HashSet<>();
|
||||||
|
for(PropertyDescriptor pd : pds) {
|
||||||
|
Object srcValue = src.getPropertyValue(pd.getName());
|
||||||
|
if (srcValue == null) emptyNames.add(pd.getName());
|
||||||
|
}
|
||||||
|
String[] result = new String[emptyNames.size()];
|
||||||
|
return emptyNames.toArray(result);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登录重试信息存入redis
|
* 登录重试信息存入redis
|
||||||
* @param username
|
* @param username
|
||||||
|
|||||||
+35
@@ -0,0 +1,35 @@
|
|||||||
|
package com.jero.modules.docking.iam.controller;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.jero.common.api.vo.Result;
|
||||||
|
import com.jero.modules.system.entity.Oauth;
|
||||||
|
import com.jero.modules.system.service.ILoginService;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: 31318
|
||||||
|
* @Date: 2023/10/17/10:09
|
||||||
|
* @Description:
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/iam")
|
||||||
|
@Slf4j
|
||||||
|
public class IamLoginController {
|
||||||
|
private final ILoginService loginService;
|
||||||
|
|
||||||
|
public IamLoginController(ILoginService loginService) {
|
||||||
|
this.loginService = loginService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("单点登录")
|
||||||
|
@PostMapping("/loginByOauth2")
|
||||||
|
public Result<JSONObject> loginByOauth2(@Validated @RequestBody Oauth oauth){
|
||||||
|
return loginService.loginByOauth2(oauth);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -384,4 +384,19 @@ hiwork:
|
|||||||
# 统一待办集成
|
# 统一待办集成
|
||||||
todoUrl: taskapi/task.basedata/integrationCall/workflowIntegration
|
todoUrl: taskapi/task.basedata/integrationCall/workflowIntegration
|
||||||
# 统一消息集成
|
# 统一消息集成
|
||||||
messageUrl: taskapi/task.basedata/notice/noticeCalls/send
|
messageUrl: taskapi/task.basedata/notice/noticeCalls/send
|
||||||
|
|
||||||
|
# 单点登录配置(所有配置信息需要协调注册,现在都为假)
|
||||||
|
oauth:
|
||||||
|
# 客户端应用注册ID
|
||||||
|
clientId: 50448-a720-903ed
|
||||||
|
# 客户端应用注册密钥
|
||||||
|
clientSecret: 0e222cb-9df9-7b97-121b4eaa
|
||||||
|
# 授权码验证
|
||||||
|
grantType: authorization_code
|
||||||
|
# 通过授权码获取accessToken请求地址
|
||||||
|
accessTokenUrl: https://认证接口地址/idp/oauth2/getToken
|
||||||
|
# 通过accessToken获取账号信息请求地址
|
||||||
|
userInfoUrl: https://认证接口地址/idp/oauth2/getUserInfo
|
||||||
|
# 防止跨站请求伪造(CSRF)标识(暂时不用)
|
||||||
|
state: zhongQi
|
||||||
Reference in New Issue
Block a user