提交 8ffdfae1 编写于 作者: laizhilong's avatar laizhilong

微信授权登录、钉钉授权登录

上级 fefb0d0c
......@@ -17,7 +17,6 @@
if (code && state) {
// 通过授权code请求后台
// alert(window.location.hostname);
var opt = {"code": code, "state": state};
$.ajax({
type: "post",
......@@ -41,9 +40,8 @@
// 跳转首页
window.location.href = "../index";
} else {
// 跳转微信绑定
alert("跳转到微信")
window.location.href = "../#/weixinLoginRedirect?code=" + code + "&state=" + state;
// 跳转钉钉绑定
window.location.href = "../#/dingdingLoginRedirect?code=" + code + "&state=" + state;
}
}
},
......@@ -54,7 +52,7 @@
}
});
} else {
alert("微信授权登录失败!");
alert("钉钉授权登录失败!");
// 回到登录页
window.location.href = "../";
}
......
......@@ -17,7 +17,6 @@
if (code && state) {
// 通过授权code请求后台
// alert(window.location.hostname);
var opt = {"code": code, "state": state};
$.ajax({
type: "post",
......
.login {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
min-height: 100%;
background: #108cee;
> img {
width: 100vw;
height: 100vh;
min-width: 1280px;
min-height: 720px;
}
&-con {
position: absolute;
left: 0;
right: 0;
top: 150px;
margin: auto;
width: 450px;
.ivu-card-head {
padding: 30px 6px;
border-bottom: 0px;
> p {
line-height: 24px;
height: 24px;
margin-bottom: -2px;
font-size: 24px;
color: #666666;
font-weight: 700;
}
}
&-header {
font-size: 16px;
font-weight: 300;
text-align: center;
padding: 30px 0;
}
.form-con {
padding: 0px 20px 0px 20px;
> i-button {
width: 170px;
height: 40px;
}
}
}
}
.log_footer {
display: block;
padding: 0 16px;
margin: 48px 0 24px;
text-align: center;
color: #212529;
}
.log_footer a {
color: white;
text-decoration: none;
}
.goLogin {
float: right;
font-size: 16px;
margin-right: 30px;
text-decoration: underline;
}
.confirm_register {
height: 40px;
font-size: 18px;
font-family: MicrosoftYaHei;
}
.disabled {
background-color: #ddd;
border-color: #ddd;
color: #57a3f3;
cursor: not-allowed; // 鼠标变化
}
\ No newline at end of file
此差异已折叠。
......@@ -439,27 +439,6 @@
}
/**
* 打开一个新窗口
* @param url 链接地址
* @param title 窗口标题
* @param w 窗口宽度
* @param h 窗口高度
*/
public openWindow(url: any, title: any, w: any, h: any): void {
const dualScreenLeft = window.screenLeft;
const dualScreenTop = window.screenTop;
const width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width;
const height = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height;
const left = ((width / 2) - (w / 2)) + dualScreenLeft;
const top = ((height / 2) - (h / 2)) + dualScreenTop;
const newWindow = window.open(url, title, 'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=yes, copyhistory=no, width=' + w + ', height=' + h + ', top=' + top + ', left=' + left);
if (window.focus && newWindow) {
newWindow.focus();
}
}
}
</script>
......
.login {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
min-height: 100%;
background: #108cee;
> img {
width: 100vw;
height: 100vh;
min-width: 1280px;
min-height: 720px;
}
&-con {
position: absolute;
left: 0;
right: 0;
top: 150px;
margin: auto;
width: 450px;
.ivu-card-head {
padding: 30px 6px;
border-bottom: 0px;
> p {
line-height: 24px;
height: 24px;
margin-bottom: -2px;
font-size: 24px;
color: #666666;
font-weight: 700;
}
}
&-header {
font-size: 16px;
font-weight: 300;
text-align: center;
padding: 30px 0;
}
.form-con {
padding: 0px 20px 0px 20px;
> i-button {
width: 170px;
height: 40px;
}
}
}
}
.log_footer {
display: block;
padding: 0 16px;
margin: 48px 0 24px;
text-align: center;
color: #212529;
}
.log_footer a {
color: white;
text-decoration: none;
}
.goLogin {
float: right;
font-size: 16px;
margin-right: 30px;
text-decoration: underline;
}
.confirm_register {
height: 40px;
font-size: 18px;
font-family: MicrosoftYaHei;
}
.disabled {
background-color: #ddd;
border-color: #ddd;
color: #57a3f3;
cursor: not-allowed; // 鼠标变化
}
\ No newline at end of file
此差异已折叠。
......@@ -12,6 +12,10 @@ export const globalRoutes:Array<any> = [
path: '/weixinLoginRedirect',
component: ()=> import('@components/login/weixinLoginRedirect.vue'),
},
{
path: '/dingdingLoginRedirect',
component: ()=> import('@components/login/dingdingLoginRedirect.vue'),
},
];
//用户自定义首页路由
export const indexRoutes:Array<any> = [
......
......@@ -106,18 +106,18 @@ public class DevBootSecurityConfig extends WebSecurityConfigurerAdapter {
.antMatchers("/syspssystems/save").permitAll()
.antMatchers("/uaa/login").permitAll()
.antMatchers("/uaa/register").permitAll()
.antMatchers("/uaa/thirdPartRegister").permitAll()
.antMatchers("/uaa/responseTokenToWeiXin").permitAll()
.antMatchers("/uaa/getWechatAppId").permitAll()
.antMatchers("/uaa/queryWechatUserByCode").permitAll()
.antMatchers("/uaa/getWechatUserInfoByCode").permitAll()
.antMatchers("/uaa/bindWechatToRegister").permitAll()
.antMatchers("/uaa/getDingtalkAppId").permitAll()
.antMatchers("/uaa/queryDingtalkUserByCode").permitAll()
.antMatchers("/uaa/getDingtalkUserInfoByCode").permitAll()
.antMatchers("/uaa/bindDingtalkToRegister").permitAll()
.antMatchers("/uaa/queryQQUserByCode").permitAll()
.antMatchers("/uaa/getQQAppId").permitAll()
.anyRequest().authenticated()
// 防止iframe 造成跨域
.and().headers().frameOptions().disable();
......
package cn.ibizlab.core.uaa.extensions.service;
import cn.ibizlab.util.domain.IBZUSER;
import cn.ibizlab.util.errors.BadRequestAlertException;
import cn.ibizlab.util.service.IBZUSERService;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.client.identify.Base64;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
/**
* 实体[IBZUSER] 钉钉用户注册接口实现
*/
@Service
@Slf4j
public class UserDingtalkRegisterService {
@Autowired
private IBZUSERService ibzuserService;
/**
* 注册
*
* @param ibzuser
* @return
*/
public IBZUSER toRegister(IBZUSER ibzuser) {
// 创建ibzuser
boolean flag = ibzuserService.save(ibzuser);
if (!flag) {
return null;
}
return ibzuser;
}
/**
* 钉钉服务端通过临时授权码code获取授权用户的个人信息
*
* @param code
* @param currentTimeMillis
* @param dingTalkAppId
* @param dingTalkAppSecret
* @return
*/
public JSONObject requestDingtalkUserByCode(String code, long currentTimeMillis, String dingTalkAppId, String dingTalkAppSecret) {
JSONObject returnObj = null;
try {
// 根据timestamp, appSecret计算签名值
String stringToSign = String.valueOf(currentTimeMillis);
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(dingTalkAppSecret.getBytes("UTF-8"), "HmacSHA256"));
byte[] signatureBytes = mac.doFinal(stringToSign.getBytes("UTF-8"));
String signature = new String(Base64.encodeBase64(signatureBytes));
String urlEncodeSignature = URLEncoder.encode(signature, "UTF-8");
// 通过临时授权码Code获取用户信息,临时授权码只能使用一次
String url = "https://oapi.dingtalk.com/sns/getuserinfo_bycode?accessKey=" + dingTalkAppId
+ "&timestamp=" + String.valueOf(currentTimeMillis)
+ "&signature=" + urlEncodeSignature;
// 创建httpclient对象
CloseableHttpClient client = HttpClients.createDefault();
// 创建post方式请求对象
HttpPost httpPost = new HttpPost(url);
// 装填参数
JSONObject param = new JSONObject();
param.put("tmp_auth_code", code);
StringEntity jsonBody = new StringEntity(param.toString(), "UTF-8");
// 设置参数到请求对象中
httpPost.setEntity(jsonBody);
// 设置header信息
httpPost.setHeader("Content-type", "application/json");
httpPost.setHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
// 执行请求操作,并拿到结果(同步阻塞)
CloseableHttpResponse response = client.execute(httpPost);
// 获取结果实体
HttpEntity entity = response.getEntity();
JSONObject entityJson = null;
if (entity != null) {
//按指定编码转换结果实体为String类型
entityJson = JSONObject.parseObject(EntityUtils.toString(entity, "UTF-8"));
}
// 是否获取钉钉用户信息成功
if (entityJson.containsKey("user_info")) {
returnObj = entityJson.getJSONObject("user_info");
} else {
throw new BadRequestAlertException("code获取钉钉用户信息失败", "UserDingtalkRegisterService", "");
}
} catch (NoSuchAlgorithmException | InvalidKeyException | IOException e) {
throw new BadRequestAlertException("钉钉生成安全签名失败", "UserDingtalkRegisterService", "");
}
return returnObj;
}
}
\ No newline at end of file
package cn.ibizlab.core.uaa.extensions.service;
import cn.ibizlab.util.domain.IBZUSER;
import cn.ibizlab.util.errors.BadRequestAlertException;
import cn.ibizlab.util.helper.HttpUtils;
import cn.ibizlab.util.service.IBZUSERService;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import java.io.UnsupportedEncodingException;
/**
* 实体[IBZUSER] 微信用户注册接口实现
*/
@Service
@Slf4j
public class UserWechatRegisterService {
@Autowired
private IBZUSERService ibzuserService;
/**
* 注册
*
* @param ibzuser
* @return
*/
public IBZUSER toRegister(IBZUSER ibzuser) {
// 创建ibzuser
boolean flag = ibzuserService.save(ibzuser);
if (!flag) {
return null;
}
return ibzuser;
}
/**
* 通过code获取微信用户信息
*
* @param code
* @param state
* @param wechatAppId
* @param wechatappsecret
* @return
*/
public JSONObject requestWechatUserByCode(String code, String state, String wechatAppId, String wechatappsecret) {
JSONObject returnObj = null;
try {
// 1.根据code获取access_token
String getAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + wechatAppId + "&secret=" + wechatappsecret + "&code=" + code + "&grant_type=authorization_code";
JSONObject responseObj = JSONObject.parseObject(HttpUtils.get(getAccessTokenUrl, null, null));
if (!responseObj.containsKey("access_token") && !responseObj.containsKey("openid")) {
throw new BadRequestAlertException("获取access_token失败!", "UserWechatRegisterService", "");
}
String access_token = responseObj.getString("access_token");
String openid = responseObj.getString("openid");
String refresh_token = responseObj.getString("refresh_token");
// 2.检验授权凭证(access_token)是否有效
String checkAccessTokenUrl = "https://api.weixin.qq.com/sns/auth?access_token=" + access_token + "&openid=" + responseObj.get("openid");
JSONObject responseObj2 = JSONObject.parseObject(HttpUtils.get(checkAccessTokenUrl, null, null));
if (responseObj2.getInteger("errcode") != 0) {
// access_token已失效,使用refresh_token进行刷新
String refreshAccess_token = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=" + wechatAppId + "&grant_type=refresh_token&refresh_token=" + refresh_token;
JSONObject responseObj3 = JSONObject.parseObject(HttpUtils.get(refreshAccess_token, null, null));
if (!responseObj3.containsKey("access_token") || !responseObj3.containsKey("openid")) {
throw new BadRequestAlertException("重新获取access_token失败!", "UserWechatRegisterService", "");
}
openid = responseObj3.getString("openid");
access_token = responseObj3.getString("access_token");
}
// 3.access_token有效,拉取用户信息(需scope为 snsapi_userinfo)
String getweChatUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=" + access_token + "&openid=" + openid + "&lang=zh_CN";
returnObj = JSONObject.parseObject(HttpUtils.get(getweChatUserInfoUrl, null, null));
if (StringUtils.isEmpty(returnObj) || returnObj.containsKey("errcode")) {
throw new BadRequestAlertException("拉取微信用户信息失败!", "UserWechatRegisterService", "");
}
} catch (UnsupportedEncodingException e) {
throw new BadRequestAlertException("获取微信授权用户相关信息失败!", "UserWechatRegisterService", "");
}
return returnObj;
}
}
\ No newline at end of file
package cn.ibizlab.api.rest.extensions;
import cn.ibizlab.core.uaa.extensions.service.UserDingtalkRegisterService;
import cn.ibizlab.core.uaa.service.ISysPSSystemService;
import cn.ibizlab.util.domain.IBZUSER;
import cn.ibizlab.util.errors.BadRequestAlertException;
import cn.ibizlab.util.helper.CachedBeanCopier;
import cn.ibizlab.util.security.AuthTokenUtil;
import cn.ibizlab.util.security.AuthenticationUser;
import cn.ibizlab.util.service.AuthenticationUserService;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@RestController
public class UserDingtalkRegisterResource {
@Autowired
private UserDingtalkRegisterService userDingtalkRegisterService;
@Autowired
private ISysPSSystemService iSysPSSystemService;
@Autowired
private AuthTokenUtil jwtTokenUtil;
@Autowired
@Qualifier("UAAUserService")
private AuthenticationUserService userDetailsService;
@Value("${ibiz.auth.dingtalk.appid:dingoatysxi5rpbluqgzpk}")
private String DingtalkAppid;
@Value("${ibiz.auth.dingtalk.appid:z2SuCSciWQJ6VSFX8jvHzTF0G_rEmHpjHrZct0rGnWrLyl8cZiRny72244EvF4SO}")
private String DingtalkAppSecret;
@Value("${ibiz.auth.dingtalk.openid:}")
private String DingtalkOpenid;
@Value("${ibiz.auth.dingtalk.nickname:}")
private String DingtalkNickname;
/**
* 获取钉钉开放平台创建的网站应用appid
*/
@GetMapping(value = "/uaa/getDingtalkAppId")
public ResponseEntity<JSONObject> getDingtalkAppId() {
JSONObject obj = new JSONObject();
String appid = DingtalkAppid;
if (!StringUtils.isEmpty(appid)) {
obj.put("appid", appid);
}
return ResponseEntity.ok(obj);
}
/**
* 根据code查钉钉用户
*
* @param param
* @return
*/
@PostMapping(value = "/uaa/queryDingtalkUserByCode")
public ResponseEntity<JSONObject> queryDingtalkUserByCode(@RequestBody JSONObject param) {
JSONObject object = new JSONObject();
// 空校验
String code = param.getString("code");
if (StringUtils.isEmpty(code))
throw new BadRequestAlertException("code为空", "UserDingtalkRegisterResource", "");
// 通过code获取钉钉用户信息
String openid = null;
String nickname = null;
long currentTimeMillis = System.currentTimeMillis();
JSONObject returnObj = userDingtalkRegisterService.requestDingtalkUserByCode(code, currentTimeMillis, DingtalkAppid, DingtalkAppSecret);
if (!StringUtils.isEmpty(returnObj) && !returnObj.containsKey("errcode")) {
openid = returnObj.getString("openid");
nickname = returnObj.getString("nick");
// 将用户信息存到缓存,供当前人后续请求使用
DingtalkOpenid = openid;
DingtalkNickname = nickname;
}
//根据openid查用户
String sql = "select * from ibzuser where avatar=#{et.avatar}";
Map<String, Object> sqlParam = new HashMap<>();
sqlParam.put("avatar", openid);
List<JSONObject> select = iSysPSSystemService.select(sql, sqlParam);
if (select.size() > 0) {
IBZUSER ibzuser = select.get(0).toJavaObject(IBZUSER.class);
object.put("ibzuser", ibzuser);
userDetailsService.resetByUsername(ibzuser.getLoginname());
AuthenticationUser user = userDetailsService.loadUserByLogin(ibzuser.getLoginname(), ibzuser.getPassword());
final String token = jwtTokenUtil.generateToken(user);
AuthenticationUser user2 = new AuthenticationUser();
CachedBeanCopier.copy(user, user2);
user2.setAuthorities(null);
user2.setPermissionList(null);
object.put("token", token);
object.put("user", user2);
}
return ResponseEntity.ok().body(object);
}
/**
* 根据code获取钉钉用户信息
*
* @param param
* @return
*/
@PostMapping(value = "/uaa/getDingtalkUserInfoByCode")
public ResponseEntity<JSONObject> getDingtalkUserInfoByCode(@RequestBody JSONObject param) {
JSONObject object = new JSONObject();
// 空校验
String code = param.getString("code");
if (StringUtils.isEmpty(code))
throw new BadRequestAlertException("code为空", "UserDingtalkRegisterResource", "");
// 通过code获取微信用户信息
String openid = DingtalkOpenid;
String nickname = DingtalkNickname;
object.put("openid", openid);
object.put("nickname", nickname);
return ResponseEntity.ok().body(object);
}
/**
* 绑定钉钉并注册
*
* @param param
* @return
*/
@PostMapping(value = "/uaa/bindDingtalkToRegister")
public ResponseEntity<JSONObject> thirdPartRegister(@RequestBody JSONObject param) {
JSONObject object = new JSONObject();
// 空校验
String loginname = param.getString("loginname");
String password = param.getString("password");
String openid = param.getString("openid");
if (StringUtils.isEmpty(openid)) {
openid = DingtalkOpenid;
}
String nickname = param.getString("nickname");
if (StringUtils.isEmpty(nickname)) {
nickname = DingtalkNickname;
}
if (StringUtils.isEmpty(loginname))
throw new BadRequestAlertException("用户名为空", "UserDingtalkRegisterResource", "");
if (StringUtils.isEmpty(password))
throw new BadRequestAlertException("密码为空", "UserDingtalkRegisterResource", "");
// 检查用户名是否已被注册
String sql = "select loginname from ibzuser where loginname=#{et.loginname}";
Map<String, Object> sqlParam = new HashMap<>();
sqlParam.put("loginname", loginname);
List<JSONObject> select = iSysPSSystemService.select(sql, sqlParam);
if (select.size() > 0)
throw new BadRequestAlertException("该用户名已被注册", "UserDingtalkRegisterResource", "");
IBZUSER ibzuser = new IBZUSER();
if (StringUtils.isEmpty(openid)) {
// 钉钉授权code已失效,重新授权
throw new BadRequestAlertException("钉钉授权已失效,请重新授权","UserDingtalkRegisterResource","");
} else {
// 已经有钉钉用户信息直接注册
String uuid = UUID.randomUUID().toString();
ibzuser.setPassword(password);
ibzuser.setLoginname(loginname);
ibzuser.setUserid("dingtalk-" + uuid);
ibzuser.setPersonname(nickname);
ibzuser.setAvatar(openid);
userDingtalkRegisterService.toRegister(ibzuser);
}
// 注册成功,登录系统
if (!StringUtils.isEmpty(ibzuser)) {
object.put("ibzuser", ibzuser);
}
// 生成登录token信息
userDetailsService.resetByUsername(ibzuser.getLoginname());
AuthenticationUser user = userDetailsService.loadUserByLogin(ibzuser.getLoginname(), ibzuser.getPassword());
final String token = jwtTokenUtil.generateToken(user);
AuthenticationUser user2 = new AuthenticationUser();
CachedBeanCopier.copy(user, user2);
user2.setAuthorities(null);
user2.setPermissionList(null);
object.put("token", token);
object.put("user", user2);
return ResponseEntity.ok().body(object);
}
}
package cn.ibizlab.api.rest.extensions;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserQQRegisterResource {
@Value("${ibiz.auth.qq.appid:101881963}")
private String qqAppId;// qq互联appid
@Value("${ibiz.auth.qq.appkey:}")
private String qqAppKey;// qq互联appkey
@Value("${ibiz.auth.qq.redirect_uri:}")
private String qqRedirectUri;// qq互联应用回调地址
}
Markdown 格式
0% or
您添加了 0 到此讨论。请谨慎行事。
先完成此消息的编辑!
想要评论请 注册