spring boot + vue3 接入钉钉实现扫码登录

1:准备工作

1.1:进入钉钉开放平台创建开发者应用。应用创建和类型介绍,参考下方。

应用类型介绍 - 钉钉开放平台 (dingtalk.com)

应用能力介绍 - 钉钉开放平台 (dingtalk.com)

扫码登录第三方网站 - 钉钉开放平台 (dingtalk.com)

1.2:创建好的应用,给对应权限。

我开通了个人权限和通讯录管理所有权限,建议是全部员工,因为这个权限只能api的权限,不会影响钉钉的权限

2:扫码登录具体实现和效果

2.1 前端和后端代码展示(前端不是很会)

工作流程介绍

用户扫码-->授权之后重定向给钉钉处理返回一个code--->钉钉处理之后执行回调域名并且携带code-->调用getBycodeResponse接口返回unionid --> 然后调用scanCodeLogin 登录接口---->成功之后进入首页。

先在 index.html 内引入一段脚本:

<script src="https://g.alicdn.com/dingding/dinglogin/0.0.5/ddLogin.js"></script>

再编写如下代码:

const redirect_uri = 'http://192.168.0.137:3000/#/ddlogin';

onMounted(()=>{

const url = encodeURIComponent(redirect_uri);

const goto = encodeURIComponent('https://oapi.dingtalk.com/connect/oauth2/sns_authorize?appid=%E4%BD%A0%E7%9A%84APP_ID&response_type=code&scope=snsapi_login&state=STATE&redirect_uri=https://oapi.dingtalk.com/connect/oauth2/sns_authorize?appid=%E4%BD%A0%E7%9A%84APP_ID&response_type=code&scope=snsapi_login&state=STATE&redirect_uri=' + url);

const obj = window.DDLogin({

id:"ddLogin",

goto,

style: "border: none",

width : "350",

height: "350"

});

});

const handleMessage = function (event: any) {

const origin = event.origin;

if( origin == "https://login.dingtalk.com" ) { //判断是否来自ddLogin扫码事件。

// 下面这个连接会在钉钉那边处理完毕之后直接让浏览器的URL变成 redirect_uri

location.href = 'https://oapi.dingtalk.com/connect/oauth2/sns_authorize?appid=%E4%BD%A0%E7%9A%84APP_ID&response_type=code&scope=snsapi_login&state=STATE&redirect_uri=https://oapi.dingtalk.com/connect/oauth2/sns_authorize?appid=%E4%BD%A0%E7%9A%84APP_ID&response_type=code&scope=snsapi_login&state=STATE&redirect_uri='+ encodeURIComponent(redirect_uri) + '&loginTmpCode=' + event.data;

}

};收起链接预览无权限https://oapi.dingtalk.com/connect/oauth2/sns_authorize?appid=dingtalk.com无权限https://oapi.dingtalk.com/connect/oauth2/sns_authorize?appid=dingtalk.com

复制代码
@ApiOperation(value = "根据sns临时授权码获取用户信息", notes = "根据sns临时授权码获取用户信息")
@RequestMapping(value = "/getBycodeResponse", method = RequestMethod.GET)
public OapiSnsGetuserinfoBycodeResponse getBycodeResponse(@RequestParam(value = "authCode")String authCode) throws JsonProcessingException, ApiException {
    OapiSnsGetuserinfoBycodeResponse bycodeResponse = sampleUtlis.getBycodeResponse(authCode, AppKey, appSecret);
    return  bycodeResponse;

}
复制代码
/**
 * 退出登录
 * @return
 */
@ApiOperation(value = "扫码登录验证", notes = "扫码登录验证")
@GetMapping(value = "/scanCodeLogin")
public Result<Object> scanCodeLogin(@RequestParam("unionid") String unionid, HttpServletResponse response) {
    Result<Object>  result=new Result<>();
    try {
        ZuodouUser zuodouUser = zuodouUserMapper.selectOne(new LambdaQueryWrapper<ZuodouUser>().eq(StringUtils.isNotBlank(unionid), ZuodouUser::getUnionid, unionid));
        if (null==zuodouUser){
            result.error500("查无此人");
            return result;
        }
        String username = zuodouUser.getUsername();
        //判断用户是否存在
        ZuodouUser  bannerItem=zuodouUserMapper.selectOne(new LambdaQueryWrapper<ZuodouUser>().eq(ZuodouUser::getUsername,username));
        result =iZuodouUserService.verifyaccount(bannerItem);
        if(!result.isSuccess()) {
            return result;
        }
        UserModel userModel=new UserModel();
        BeanUtils.copyProperties(bannerItem,userModel);
        List<ZuodouUserRole> zuodouUserRoles = zuodouUserRoleService.list(new LambdaQueryWrapper<ZuodouUserRole>().eq(ZuodouUserRole::getUserId, bannerItem.getId()).eq(ZuodouUserRole::getStatus, StatusEum.getNameValue(CommonConstant.STATUSNAME_A)));
        if (!CollectionUtils.isEmpty(zuodouUserRoles)){
            userModel.setRole(zuodouUserRoles.stream().map(s->s.getRoleId()).collect(Collectors.toList()));
            List<String> zuodouRolePermissions = zuodouRolePermissionMapper.listPermission(userModel.getRole());
            if (!CollectionUtils.isEmpty(zuodouRolePermissions)){
                userModel.setPermission(zuodouRolePermissions);
            }
        }

        zuodouUser.setLastLogin(new Date());
        zuodouUserMapper.updateById(zuodouUser);
        String jwtToken = JwtUtils.getJwtToken(userModel);
        Cookie cookie = new Cookie(userTokenUtils.getTokenCode(), jwtToken);
        cookie.setPath("/");
        cookie.setMaxAge(Math.toIntExact(CommonConstant.TOKEN_EXPIRE));
        response.addCookie(cookie);
        //先删除key
        redisUtil.del(userTokenUtils.getTokenCode()+bannerItem.getId());
        redisUtil.set(userTokenUtils.getTokenCode() + bannerItem.getId(), jwtToken,CommonConstant.REDIS_EXPIRE*2);
        log.info(userTokenUtils.getTokenCode() + bannerItem.getId());
        Map<String,Object> map=new HashMap<>();
        map.put(CommonConstant.TOKEN_MODEL,bannerItem);
        map.put(userTokenUtils.getTokenCode(),jwtToken);
        result.setResult(map);
        result.success("登录成功");
    } catch (Exception e) {
        e.printStackTrace();
        result.error500("操作失败");
    }
    return result;
}
相关推荐
皮皮林55111 小时前
拒绝写重复代码,试试这套开源的 SpringBoot 组件,效率翻倍~
java·spring boot
用户908324602733 天前
Spring AI 1.1.2 + Neo4j:用知识图谱增强 RAG 检索(上篇:图谱构建)
java·spring boot
用户8307196840824 天前
Spring Boot 集成 RabbitMQ :8 个最佳实践,杜绝消息丢失与队列阻塞
spring boot·后端·rabbitmq
Java水解4 天前
Spring Boot 视图层与模板引擎
spring boot·后端
Java水解4 天前
一文搞懂 Spring Boot 默认数据库连接池 HikariCP
spring boot·后端
洋洋技术笔记4 天前
Spring Boot Web MVC配置详解
spring boot·后端
初次攀爬者5 天前
Kafka 基础介绍
spring boot·kafka·消息队列
用户8307196840825 天前
spring ai alibaba + nacos +mcp 实现mcp服务负载均衡调用实战
spring boot·spring·mcp
Java水解5 天前
SpringBoot3全栈开发实战:从入门到精通的完整指南
spring boot·后端
初次攀爬者6 天前
RocketMQ在Spring Boot上的基础使用
java·spring boot·rocketmq