LoginDdController.java 7.42 KB
package com.chinagas.auth.controller;

import com.chinagas.api.system.RemoteUserService;
import com.chinagas.api.system.domain.SysUser;
import com.chinagas.api.system.domain.SysUserUnite;
import com.chinagas.api.system.model.LoginUser;
import com.chinagas.auth.service.LoginLogService;
import com.chinagas.auth.utils.DingingCodeProperties;
import com.chinagas.common.core.constants.Constants;
import com.chinagas.common.core.constants.SecurityConstants;
import com.chinagas.common.core.domain.R;
import com.chinagas.common.core.enums.UserStatus;
import com.chinagas.common.core.exceptions.ServiceException;
import com.chinagas.common.core.utils.StringUtils;
import com.chinagas.common.security.service.TokenService;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiGettokenRequest;
import com.dingtalk.api.request.OapiV2UserGetRequest;
import com.dingtalk.api.request.OapiV2UserGetuserinfoRequest;
import com.dingtalk.api.response.OapiGettokenResponse;
import com.dingtalk.api.response.OapiV2UserGetResponse;
import com.dingtalk.api.response.OapiV2UserGetuserinfoResponse;
import com.taobao.api.ApiException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.Calendar;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName LoginDdController
 * @Author zhl
 * @Description 钉钉免登录
 * @CreateTime 2023/11/13
 */
@Slf4j
@RestController
@RequestMapping("/dingding")
public class LoginDdController {
    @Autowired
    private DingingCodeProperties dingingCodeProperties;
    @Autowired
    private RemoteUserService remoteUserService;
    @Autowired
    private LoginLogService loginLogService;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private RedisTemplate redisTemplate;


    @RequestMapping("/login")
    public R<?> login(@RequestParam("code") String code) {
        try {
            // 获取access_token
            String access_token = getToken();
            if (access_token == null) {
                throw new RuntimeException("access_token为空");
            }
            // 获取userId
            DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/getuserinfo");
            OapiV2UserGetuserinfoRequest req = new OapiV2UserGetuserinfoRequest();
            req.setCode(code);
            OapiV2UserGetuserinfoResponse rsp = client.execute(req, access_token);
            String userid = rsp.getResult().getUserid();
            if (userid == null) {
                throw new RuntimeException("userid为空");
            }
            // 根据userId获取用户信息
            DingTalkClient clientDingTalkClient2 = new DefaultDingTalkClient(
                    "https://oapi.dingtalk.com/topapi/v2/user/get");
            OapiV2UserGetRequest reqGetRequest = new OapiV2UserGetRequest();
            reqGetRequest.setUserid(userid);
            reqGetRequest.setLanguage("zh_CN");
            OapiV2UserGetResponse rspGetResponse = clientDingTalkClient2.execute(reqGetRequest, access_token);
            // 获取username
            String extension = rspGetResponse.getResult().getExtension();
            if (extension.equals("{}")) {
                throw new RuntimeException("非钉钉内部账号");
            }
            int firstQuoteIndex = extension.indexOf(":\"") + 2;
            int secondQuoteIndex = extension.indexOf("\"", firstQuoteIndex + 1);
            String username = extension.substring(firstQuoteIndex, secondQuoteIndex);
//            String username = rsp.getResult().getName();
//            if (username == null) {
//                throw new RuntimeException("username为空");
//            }
            LoginUser userInfo = getUserInfo(username);
            // 登录量统计
            redisTemplate.opsForValue().increment("user_login_count_" + username, 1);
            // 计算到0点秒数
            Calendar cal = Calendar.getInstance();
            cal.add(Calendar.DAY_OF_YEAR, 1);
            cal.set(Calendar.HOUR_OF_DAY, 0);
            cal.set(Calendar.SECOND, 0);
            cal.set(Calendar.MINUTE, 0);
            cal.set(Calendar.MILLISECOND, 0);
            redisTemplate.expire("user_login_count_" + username, (cal.getTimeInMillis() - System.currentTimeMillis()) / 1000, TimeUnit.SECONDS);
            // 活跃量统计
            redisTemplate.opsForValue().increment("user_count", 1);
            redisTemplate.expire("user_count", (cal.getTimeInMillis() - System.currentTimeMillis()) / 1000, TimeUnit.SECONDS);
            // 获取登录token
            SysUserUnite sysUserUnite=new SysUserUnite();
            sysUserUnite.setUserId(userInfo.getSysUser().getUserId());
            sysUserUnite.setDingTalkUserId(userid);
            sysUserUnite.setDingTalkUnionId(rsp.getResult().getUnionid());
            remoteUserService.insertUserUnite(sysUserUnite);
            return R.ok(tokenService.createToken(userInfo));
        } catch (ApiException e) {
            e.printStackTrace();
            return R.fail("-1");
        }
    }

    public String getToken() {
        try {
            DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken");
            OapiGettokenRequest request = new OapiGettokenRequest();
            // 填写步骤一创建应用的Appkey
            request.setAppkey(dingingCodeProperties.getClientId());
            // 填写步骤一创建应用的Appsecret
            request.setAppsecret(dingingCodeProperties.getClientSecret());
            request.setHttpMethod("GET");
            OapiGettokenResponse response = client.execute(request);
            String accessToken = response.getAccessToken();
            return accessToken;
        } catch (ApiException e) {
            throw new RuntimeException();
        }
    }

    private LoginUser getUserInfo(String username) {
        // 查询用户信息
        R<LoginUser> userResult = remoteUserService.getUserInfo(username, SecurityConstants.INNER);

        if (StringUtils.isNull(userResult) || StringUtils.isNull(userResult.getData())) {
            loginLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "登录用户不存在");
            throw new ServiceException("登录用户:" + username + " 不存在");
        }

        if (R.FAIL == userResult.getCode()) {
            throw new ServiceException(userResult.getMsg());
        }

        LoginUser userInfo = userResult.getData();
        SysUser user = userResult.getData().getSysUser();
        if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) {
            loginLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "对不起,您的账号已被删除");
            throw new ServiceException("对不起,您的账号:" + username + " 已被删除");
        }
        if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
            loginLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户已停用,请联系管理员");
            throw new ServiceException("对不起,您的账号:" + username + " 已停用");
        }
        loginLogService.recordLogininfor(username, Constants.LOGIN_SUCCESS, "登录成功");
        return userInfo;
    }
}