前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >RuoYi框架集成DingDing登录

RuoYi框架集成DingDing登录

原创
作者头像
在下是首席架构师
发布2023-03-30 15:31:34
1.7K3
发布2023-03-30 15:31:34
举报
文章被收录于专栏:从入门到出门从入门到出门

集成概览

  • login.js:api定义钉钉登录接口
  • user.js:在钉钉登录成功后,设置token
  • login.vue:使用钉钉的默认集成页面进行钉钉登录
  • DingDingService.java(以及它的实现类 DingDingServiceImpl.java):访问钉钉的服务接口
  • SysLoginController.java:定义钉钉登录接口
  • pom.xml:添加钉钉服务依赖jar包
  • SecurityConfig.java:将钉钉登录接口设置为可匿名访问
  • UserDetailsServiceImpl.java:数据库查询用户(需要提前将钉钉用户创建在数据库里,可拿到钉钉的用户id之后,再插入)
  • 钉钉的开放平台的配置

图片概览

详细代码

login.js 增量代码

代码语言:javascript
复制
//查询钉钉信息
export function dingLogin(code) {
  return request({
    url: '/dingLogin?code=' + code,
    headers: {
      isToken: false
    },
    method: 'post'
  })
}

user.js 增量代码

代码语言:javascript
复制
actions: {
    dingLogin({commit},token){
      return new Promise((resolve,reject)=>{
        setToken(token)
        commit('SET_TOKEN', token)
        resolve()
      })

    }
}

login.vue 增量代码

代码语言:html
复制
import { getCodeImg, dingLogin } from "@/api/login";

mounted() {
    // 钉钉登录
    this.handleGetDingLoginInfo(()=>{
      this.handleDingLogin();
    });

  },

methods: {
    // 获取钉钉配置信息
    handleGetDingLoginInfo(callback){
      callback();
    },

    handleDingLogin(){
      if(this.$route.query){
        var jsonStr = JSON.stringify(this.$route.query);

        let string = jsonStr.split('authCode=')[1];
        if(string){
          this.$route.query.authCode = string.substring(0, 32);
        }
      }

      if (!this.$route.query.authCode) {
        window.location.href='https://login.dingtalk.com/oauth2/auth?' +
          'redirect_uri=' + 'http%3A%2F%2F127.0.0.1:80%2Findex' +
          '&response_type=code' +
          '&client_id=' + APPID +
          '&scope=snsapi_login' +
          '&state=dddd' +
          '&prompt=consent'
      } else {
        dingLogin(this.$route.query.authCode)
          .then(resp=>{
            if(resp.code === 500){
              this.$notify.error({
                title: '错误',
                message: '没有查询到你的登录权限。请关闭重新打开,或联系管理员授权',
                duration: 0
              });
            }else{
              this.$store.dispatch('dingLogin',resp.token).then(resp=>{
                this.$notify({
                  title: '成功',
                  message: '已成功登录系统'
                });
                this.$router.push({path: "/"})
              })
            }

          })
      }
    }
}

DingDingService 全量代码

代码语言:java
复制
import com.alibaba.fastjson2.JSONObject;

/**
 * write something here
 *
 * @author xuyt
 * @date 2023/3/29
 **/
public interface DingDingService {

    String getDingLogin(String code) throws Exception;
}

DingDingServiceImpl 全量代码

代码语言:java
复制
import com.alibaba.fastjson2.JSONObject;
import com.aliyun.dingtalkcontact_1_0.models.GetUserHeaders;
import com.aliyun.dingtalkcontact_1_0.models.GetUserResponseBody;
import com.aliyun.dingtalkoauth2_1_0.models.GetUserTokenRequest;
import com.aliyun.dingtalkoauth2_1_0.models.GetUserTokenResponse;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiGettokenRequest;
import com.dingtalk.api.request.OapiUserGetbyunionidRequest;
import com.dingtalk.api.response.OapiGettokenResponse;
import com.dingtalk.api.response.OapiUserGetbyunionidResponse;
import org.springframework.stereotype.Service;

/**
 * write something here
 *
 * @author xuyt
 * @date 2023/3/29
 **/
@Service
public class DingDingServiceImpl implements DingDingService {
    private com.aliyun.dingtalkoauth2_1_0.Client authClient() throws Exception {
        Config config = new Config();
        config.protocol = "https";
        config.regionId = "central";
        return new com.aliyun.dingtalkoauth2_1_0.Client(config);
    }

    private com.aliyun.dingtalkcontact_1_0.Client contactClient() throws Exception {
        Config config = new Config();
        config.protocol = "https";
        config.regionId = "central";
        return new com.aliyun.dingtalkcontact_1_0.Client(config);
    }

    /**
     * 获取用户个人信息
     *
     * @param accessToken
     * @return
     * @throws Exception
     */
    private GetUserResponseBody getUserinfo(String accessToken) throws Exception {
        com.aliyun.dingtalkcontact_1_0.Client client = contactClient();
        GetUserHeaders getUserHeaders = new GetUserHeaders();
        getUserHeaders.xAcsDingtalkAccessToken = accessToken;
        //获取用户个人信息
        return client.getUserWithOptions("me", getUserHeaders, new RuntimeOptions()).getBody();
    }

    /**
     * 通过扫描二维码返回的code值,得到用户相关信息
     */
    @Override
    public String getDingLogin(String authCode) throws Exception {

        com.aliyun.dingtalkoauth2_1_0.Client client = authClient();
        GetUserTokenRequest getUserTokenRequest = new GetUserTokenRequest()

                //应用基础信息-应用信息的AppKey,请务必替换为开发的应用AppKey
                .setClientId("APPID")

                //应用基础信息-应用信息的AppSecret,,请务必替换为开发的应用AppSecret
                .setClientSecret("APPSECRET")
                .setCode(authCode)
                .setGrantType("authorization_code");


        GetUserTokenResponse getUserTokenResponse = client.getUserToken(getUserTokenRequest);
        //获取用户个人token
        String accessToken = getUserTokenResponse.getBody().getAccessToken();
        System.out.println(accessToken);

        //获取钉钉用户信息
        GetUserResponseBody me = getUserinfo(accessToken);

        //获取 token
        DingTalkClient client4 = new DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken");
        OapiGettokenRequest request = new OapiGettokenRequest();
        request.setAppkey("APPID");
        request.setAppsecret("APPSECRET");
        request.setHttpMethod("GET");
        OapiGettokenResponse response = client4.execute(request);
        System.out.println(response.getBody());

        //根据 unionId 获取 userId
        DingTalkClient client1 = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/user/getbyunionid");
        OapiUserGetbyunionidRequest req1 = new OapiUserGetbyunionidRequest();
        req1.setHttpMethod("POST");
        req1.setUnionid(me.getUnionId());
        OapiUserGetbyunionidResponse rsp = client1.execute(req1, response.getAccessToken());
        JSONObject json = JSONObject.parseObject(rsp.getBody());
        JSONObject result = JSONObject.parseObject(json.getString("result"));
        return result.getString("userid");
    }


}

SysLoginController 全量代码

代码语言:java
复制
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.web.service.DingDingService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysMenu;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.LoginBody;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.framework.web.service.SysLoginService;
import com.ruoyi.framework.web.service.SysPermissionService;
import com.ruoyi.system.service.ISysMenuService;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 登录验证
 * 
 * @author ruoyi
 */
@RestController
public class SysLoginController
{
    @Autowired
    private SysLoginService loginService;

    @Autowired
    private ISysMenuService menuService;

    @Autowired
    private SysPermissionService permissionService;

    @Autowired
    private ISysUserService sysUserService;
    @Resource
    private UserDetailsService userDetailsService;
    @Resource
    private TokenService tokenService;

    /**
     * 登录方法
     * 
     * @param loginBody 登录信息
     * @return 结果
     */
    @PostMapping("/login")
    public AjaxResult login(@RequestBody LoginBody loginBody)
    {
        AjaxResult ajax = AjaxResult.success();
        // 生成令牌
        String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
                loginBody.getUuid());
        ajax.put(Constants.TOKEN, token);
        return ajax;
    }

    /**
     * 获取用户信息
     * 
     * @return 用户信息
     */
    @GetMapping("getInfo")
    public AjaxResult getInfo()
    {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        // 角色集合
        Set<String> roles = permissionService.getRolePermission(user);
        // 权限集合
        Set<String> permissions = permissionService.getMenuPermission(user);
        AjaxResult ajax = AjaxResult.success();
        ajax.put("user", user);
        ajax.put("roles", roles);
        ajax.put("permissions", permissions);
        return ajax;
    }

    /**
     * 获取路由信息
     * 
     * @return 路由信息
     */
    @GetMapping("getRouters")
    public AjaxResult getRouters()
    {
        Long userId = SecurityUtils.getUserId();
        List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
        return AjaxResult.success(menuService.buildMenus(menus));
    }

    @Autowired
    private DingDingService dingDingService;
    /**
     * 获取用户信息
     *
     * @return 用户信息
     */
    @PostMapping(value="/dingLogin")
    public AjaxResult dingLogin(String code) throws Exception {

        String userId = dingDingService.getDingLogin(code);
        SysUser sysUser = sysUserService.selectUserByUserName(userId);
        if (sysUser == null) {
            throw new Exception();
        }
        LoginUser loginUser = (LoginUser) userDetailsService.loadUserByUsername(userId);

        // 生成token
        AjaxResult ajax = AjaxResult.success();
        ajax.put(Constants.TOKEN, tokenService.createToken(loginUser));
        return ajax;
    }
}

pom.xml 增量代码

代码语言:html
复制
<dependencies>
    <dependency>
        <groupId>com.aliyun</groupId>
        <artifactId>alibaba-dingtalk-service-sdk</artifactId>
        <version>2.0.0</version>
    </dependency>
    <dependency>
        <groupId>com.aliyun</groupId>
        <artifactId>dingtalk</artifactId>
        <version>1.1.86</version>
    </dependency>
</dependencies>

SecurityConfig 增量代码

代码语言:txt
复制
// 对于登录login 注册register 验证码captchaImage 允许匿名访问
.antMatchers("/login", "/register", "/captchaImage", "/common/**", "/dingLogin").permitAll()

UserDetailsServiceImpl 减少代码

代码语言:java
复制
//passwordService.validate(user);

钉钉开放平台的配置

  1. 创建企业h5微应用,进入我的后台
  2. 基础信息-开发管理-开发模式,设置为开发应用
  3. 基础信息-开发管理-开发管理,将服务器出口ip设置为电脑的公网ip,查询公网ip网址:https://www.ip138.com
  4. 基础信息-开发管理-开发管理,应用首页地址、PC端首页地址、管理后台地址,都设置为 http://127.0.0.1:8080
  5. 基础信息-开发管理-权限管理,开通全部员工的全部个人权限
  6. 应用功能-登录与分享-设置回调域名,本地联调就设置为 http://127.0.0.1:8080
  7. 完.

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 集成概览
  • 图片概览
  • 详细代码
  • 钉钉开放平台的配置
相关产品与服务
验证码
腾讯云新一代行为验证码(Captcha),基于十道安全栅栏, 为网页、App、小程序开发者打造立体、全面的人机验证。最大程度保护注册登录、活动秒杀、点赞发帖、数据保护等各大场景下业务安全的同时,提供更精细化的用户体验。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档