keycloak单点登录(浙政钉2.0扫码、手机号验证码登录)

2023-10-26

写在前面:本篇博客只针对前端代码实现,keycloak配置什么的,自己和后端或者运维联调吧。说实在的,因为不熟悉keycloak代码的逻辑,再加上时间紧,所以搞了一些很多骚操作。
登录这些前端代码是写在keycloak项目里的,文件是.ftl,还好政府项目没有对UI有什么很高的要求。扫码登录和手机号验证码,成功之后是跳转到Vue项目里的。
@TOC

浙政钉扫码登录

扫码登录:

在这里插入图片描述
专有钉钉扫码登陆流程
我这里采用的时第二种实现方式,嵌入iframe,但是这样有个弊端,开发时由于跨域,无法改二维码的样式。
在这里插入图片描述

template_login.ftl
<div id="login_container">
	<!--这个时关联form表单的代码 具体代码在sms-captcha-login.ftl-->
                        <#nested "form">
                        <div class="tabContentCode active" id="frame">
                        	<!--这段代码没啥主要是遮住二维码上面的字,就是一个白色的背景区域-->
                            <div class="cover coverbg" id="cover"></div>
                            <iframe name="my-iframe" id="myFrame" 
                            src="" 
                            frameborder="0" 
                            width="310" height="310" scrolling="no"></iframe>
                        </div>
                    </div>
<#import "template_login.ftl" as layout>
<@layout.registrationLayout displayInfo=social.displayInfo displayWide=(realm.password && social.providers??); section>
    <#if realm.password && social.providers??>
    	<!--首先循环p-->
		<#list social.providers as p>
		<!--当p.providerId == "dgwork"做判断操作,但是循环了三次,没有找到具体原因,所以就做了一下操作只取第一次循环的数据,之后的全部返回-->
        <#if p.providerId == "dgwork">
			<script defer="defer">
			var num = window.localStorage.getItem('first');
			console.log("************"+num);
			if(!num){
				num = 0
				window.localStorage.setItem('first', num);
			}	
			if(num==0){
				console.log("*****11111*******");
				window.addEventListener('message', function(event) {
				  var origin = event.origin;
				  //https://openplatform-portal.dg-work.cn/portal/#/helpdoc?docKey=kfzn&slug=engk1k  下面的origin时这个地址里的各环境域名/登录域名,线上环境是login-pro.ding.zj.gov.cn
				  
				  if (origin == "https://login.dg-work.cn") {
					var loginTmpCode = event.data; 
					//取网址里的参数开始
					var search = http_url.substring(1)
					if (!search && location.href.lastIndexOf('?') > -1) {
					  search = location.href.substring(location.href.lastIndexOf('?') + 1)
					}
					var obj = {}
					if (search.length > 0) {
					  var arr = [], item
					  arr = search.split('&')
					  for (var i = arr.length; --i >= 0;) {
						item = arr[i].split('=')
						obj[item[0]] = item[1]
					  }
					}
					//取网址里的参数结束主要取往里的回调地址redirect_uri,code和state是监听返回的也是必须的
					var new_uri= decodeURIComponent(obj.redirect_uri) + '?code='+loginTmpCode.code+'&state='+loginTmpCode.state;
					try {
						//跳到新的回调地址去,也就是页面的跳转
					  top.location.assign(new_uri);
					} catch (e) {
					  top.location.href=new_uri;
					}
				  }
				})
				var http_url='';
				//htmlUtil时引入 的文件,主要用来对网址解码用的,可以自定义
				var login_url=htmlUtil.decode("${p.loginUrl}");
				
				if("${p.providerId}" == 'dgwork'){
					//这个玩意也是引入的原生js文件,可以用ajax试试
					ajaxHandler.Ajax({
					url: login_url,
					type: "get",
					success: function (result) {
						if(result.startsWith("http")){
							http_url=result;
							
							console.log(http_url + '---------1')
						}
					},
					error: function (e, status) {
					  console.log(e.responseText);
					}
				  });
				} 
				//因为不知道二维码啥时候出现,所以做了定时装置。iframe里有个onload事件,自己试了没有成功。
				var myVar = setInterval(function(){
					var frame = document.getElementById("myFrame")
					if(frame){
						document.getElementById("myFrame").src = http_url
						clearInterval(myVar)
					}
				}, 500)
				num++;
				window.localStorage.setItem('first', num);
			}
			</script>
        </#if>
      </#list>
    </#if>
    <#if section = "title">
        ${realm.displayName}
    <#elseif section = "header">
        ${msg("loginTitleHtml",realm.name)}
    <#elseif section = "form">
    </#if>
</@layout.registrationLayout>

还有一个要注意的点,我们的网址环境都是https,当跳转或者取到得是http,则会有跨域报错,因此在template_login.ftl加入了这么一行代码,但是关键点来了,开发的时候把代码注释掉,不然会报错。

<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">

看一下就好了
在这里插入图片描述

手机验证码登陆,这个就不详细说了,都是很简单的东西。[有需要的可以私聊我]

在这里插入图片描述

还有一个骚操作就是切换的时候二维码必须更新,因为扫码和手机号都是用的同一个code和state所以,切换到二维码时直接
window.location.reload()就可以了

Vue项目里也很简单

import Vue from 'vue'
import VueKeyCloak from '@dsb-norge/vue-keycloak-js'
export function basicsAuth () {
  return new Promise((resolve, reject) => {
    let userInfo = {}
    let vm = new Vue()
    Vue.use(VueKeyCloak , {
      init: {
        onLoad: 'login-required'
      },
      config: {
        url: window.OIDCPATH,
        realm: window.REALM,
        clientId: window.CLIENTID,
        logoutRedirectUri: window.location.href.split('#')[0]
      },
      onReady: keycloak => {
        // alert(JSON.stringify(keycloak))
        keycloak.updateToken()
        window.localStorage.setItem('tk', keycloak.token)
        vm.$http.defaults.headers['Authorization'] = `Bearer ` + keycloak.token
        keycloak.loadUserProfile().success(data => {
          
          userInfo = Object.assign(userInfo, data)
          let unionObj = data.attributes.authInfo[0]
          let unionId = JSON.parse(unionObj).unionid || JSON.parse(unionObj).accountId
          let type = data.attributes.authType[0]
          store.commit('SET_USER_DATA', data)
          setLocalStorage('sd', data)
          store.commit('SET_UNION_ID', unionId)
          getUserInfo(unionId, type)
        })
      },
      onInitError: err => {
        vm.$message({
          type:'error',
          message:'账号异常,请联系管理员,即将返回登录页面!',
          offset:'80'
        })
        setTimeout(function()  {
          window.location.reload();
        }, 3000);
      }
    })
    // 根据unionId获取用户信息
    function getUserInfo (unionId, type) {
      let data = {
        thirdUserId: unionId,
        thirdUserType: type
      }
      vm.$get('', data).then(res => {
        // vm.$http.defaults.headers['userId'] = res.data.userId
        vm.$destroy()
        if (res.code === 200) {
          userInfo = Object.assign(userInfo, res.data)
          resolve(userInfo)
        }
      }).catch(err => {
        console.log(err)
        vm.$destroy()
        reject(err)
      })
    }
  })
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

keycloak单点登录(浙政钉2.0扫码、手机号验证码登录) 的相关文章

随机推荐

  • 【异步编程】Promise

    Promise的基本用法 创建promise对象 Promise对象代表一个异步操作 有三种状态 pending 进行中 fulfilled 已成功 和rejected 已失败 Promise构造函数接受一个函数作为参数 该函数的两个参数分
  • Linux基础命令-正则表达式和通配符

    Linux基础命令 正则表达式和通配符 正则表达式和通配符 一 正则表达式 1 正则表达式概念 2 字符匹配 3 匹配次数 4 位置锚定 5 分组 6 后向引用 7 扩展正则表达式 二 通配符 1 通配符 2 Shell常见通配符 3 sh
  • python中类的self的含义

    import torch 省略部分代码 网络模型 预测部分 class Net1 def init self input test self inputn test scaler1 transform input test self inp
  • 排序算法之快速排序及其C语言代码实现

    概述 快速排序 Quicksort 是对冒泡排序的一种改进 快速排序由C A R Hoare在1962年提出 它的基本思想是 通过一趟排序将要排序的数据分割成独立的两部分 其中一部分的所有数据都比另外一部分的所有数据都要小 然后再按此方法对
  • IDA工具安装、分享

    往期推荐 ARM处理器寻址方式 ARM指令集 ARM汇编语言程序结构 Android与ARM处理器 IDA工具被称之为是世界顶级的交互汇编 掌握IDA工具界面上的快捷功能 导航条主界面功能以及汇编窗口常用快捷键的使用 实战分析 了解ARM指
  • 接口一定要实现序列化Serializable吗?

    背景 最近在做项目的过程中 发现一个问题 我们服务之间调用的feign接口及对外提供的接口 里面的对象都实现了序列化 但是以前我们的对外接不写序列化 也没有啥问题 在这里的时候 就有点疑惑 1 为什么要进行序列化 2 每个实体bean都必须
  • Linux内核Backlog笔记

    一 listen方法传入的backlog参数 net core somaxconn 这个参数具体意义 先看看Linux Socket的listen解释 man listen include
  • C++报错类型elemType classType::member is protected within this context的解决思路

    C 报错类型elemType classType member is protected within this context的解决思路 问题背景 在对象类尝试增加友元函数 什么是友元函数 在类中增加友元类 问题背景 在查看 lt lt
  • yolo算法

    YOLO系列算法是一类典型的one stage目标检测算法 其利用anchor box将分类与目标定位的回归问题结合起来 从而做到了高效 灵活和泛化性能好 所以在工业界也十分受欢迎 接下来我们介绍YOLO 系列算法 1 yolo算法 Yol
  • 【VMware】虚拟机不能全屏的解决方法

    之前装了vmware workstation 8 最近装上新的ubuntu发现不能全屏 网上搜索后发现是因为没有安装vmware tools 现在就将本人安装vmware tools的过程介绍如下 1 加载vmwaretools 1 如下图
  • SQL语句中的in/exist/NOT IN/NOT EXIST的联系与区别

    IN EXIST NOT IN NOT EXIST的效率比较 由于使用使用not in 进行查询时 不会使用索引 所以not in 在任何情况下 效率都是最差的 而not exist和 exist两者效率是一致的 接下来主要辨析IN和EXI
  • DAMA学习笔记

    第1章 数据管理 1 1 引言 1 数据管理 为了实现数据价值 制定计划 制度并执行 监督 2 数据管理专业人员 技术人员 数据库管理员 网络管理员 程序员 和业务人员 数据管理专员 数据策略师 首席数据官 1 1 1 业务驱动因素 信息和
  • C++ Template Class List

    转载请注明 http blog csdn net c602273091 article details 50717999 Introduction STL STL Standard Template Library 标准模板库 是惠普实验室
  • 时序分析 30 金融资产预测 - 蒙特卡洛模拟

    金融资产预测 蒙特卡洛模拟 商业经营活动中经常需要预测其收入 成本和利润 企业中的金融团队很可能会被要求构建金融模型进行场景分析 例如在不同的假设的情况下分析最好的情况 正常情况和最差的情况 这样做的目的主要是为管理层提供在不同的市场情况下
  • Overleaf latex绘制三线表

    在 begin document 前加入以下内容 usepackage array 需要用到该宏包 usepackage footnote makesavenoteenv tabular 示例 begin table htbp captio
  • Windows向日葵连接Ubuntu时“连接已断开”解决方案

    环境 控制端 Windows10 系统 向日葵版本12 5 1 44969 被控端 Ubuntu20 04 系统 默认gdm3桌面 向日葵版本11 0 0 36662 问题描述 使用windows端向日葵远程连接ubuntu主机时出现 连接
  • 【springboot】 整合 jasypt 配置信息加密

    项目集成jasypt的方式 引入jasypt spring boot加密组件 通过jasypt spring boot这个开箱即用的加密组件来引入Jasypt这个强大的加密库 方式一 在Springboot应用程序中 如果使用了 Sprin
  • 2020最新版Python学习路线图--Python基础重点知识

    Python学习路线图的第一阶段Python基础的学习 Python学习这一阶段的学习目标是掌握Python基础语法 具备基础的编程能力 建立起Python学习编程思维以及面向对象程序设计思想 能够熟练使用Python技术完成针对小问题的程
  • zipkin学习--07--Springboot 集成 Zipkin--持久化到数据库

    一 介绍 Zipkin目前只支持mysql数据库 只需要修改 Zipkin服务端 二 总体结构 代码位置 https gitee com DanShenGuiZu learnDemo tree master zipkin learn 2 1
  • keycloak单点登录(浙政钉2.0扫码、手机号验证码登录)

    写在前面 本篇博客只针对前端代码实现 keycloak配置什么的 自己和后端或者运维联调吧 说实在的 因为不熟悉keycloak代码的逻辑 再加上时间紧 所以搞了一些很多骚操作 登录这些前端代码是写在keycloak项目里的 文件是 ftl