mirror of
https://github.com/JasonsGong/JasonsGong.github.io.git
synced 2024-11-24 11:29:36 +08:00
388 lines
114 KiB
HTML
388 lines
114 KiB
HTML
<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0,viewport-fit=cover"><title>微信登录 | The Blog</title><meta name="author" content="Jason"><meta name="copyright" content="Jason"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="1、OAuth2微信登录使用了OAuth2解决方案 1.1 OAuth2解决什么问题1.1.1 开放系统间授权照片拥有者想要在云冲印服务上打印照片,云冲印服务需要访问云存储服务上的资源 1.1.2图例资源拥有者:照片拥有者 客户应用:云冲印 受保护的资源:照片 1.1.3方式一:用户名密码复制 用户将自己的”云存储”服务的用户名和密码,告诉”云冲印”,后者就可以读取用户的照片了。这样的做法有以">
|
||
<meta property="og:type" content="article">
|
||
<meta property="og:title" content="微信登录">
|
||
<meta property="og:url" content="https://qingling.icu/posts/45572.html">
|
||
<meta property="og:site_name" content="The Blog">
|
||
<meta property="og:description" content="1、OAuth2微信登录使用了OAuth2解决方案 1.1 OAuth2解决什么问题1.1.1 开放系统间授权照片拥有者想要在云冲印服务上打印照片,云冲印服务需要访问云存储服务上的资源 1.1.2图例资源拥有者:照片拥有者 客户应用:云冲印 受保护的资源:照片 1.1.3方式一:用户名密码复制 用户将自己的”云存储”服务的用户名和密码,告诉”云冲印”,后者就可以读取用户的照片了。这样的做法有以">
|
||
<meta property="og:locale" content="zh_CN">
|
||
<meta property="og:image" content="https://qingling.icu/img/5.png">
|
||
<meta property="article:published_time" content="2023-04-20T14:02:22.000Z">
|
||
<meta property="article:modified_time" content="2023-09-11T23:36:50.000Z">
|
||
<meta property="article:author" content="Jason">
|
||
<meta property="article:tag" content="Java">
|
||
<meta name="twitter:card" content="summary">
|
||
<meta name="twitter:image" content="https://qingling.icu/img/5.png"><link rel="shortcut icon" href="/img/%E5%9B%BE%E6%A0%87.png"><link rel="canonical" href="https://qingling.icu/posts/45572.html"><link rel="preconnect" href="//fastly.jsdelivr.net"/><link rel="preconnect" href="//busuanzi.ibruce.info"/><link rel="stylesheet" href="/css/index.css"><link rel="stylesheet" href="/cdn/icon/fontawesome-free/css/all.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="/cdn/css/snackbar.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="/cdn/css/fancybox.min.css" media="print" onload="this.media='all'"><script>const GLOBAL_CONFIG = {
|
||
root: '/',
|
||
algolia: undefined,
|
||
localSearch: {"path":"/search.xml","preload":true,"top_n_per_article":1,"unescape":false,"languages":{"hits_empty":"找不到您查询的内容:${query}","hits_stats":"共找到 ${hits} 篇文章"}},
|
||
translate: undefined,
|
||
noticeOutdate: undefined,
|
||
highlight: {"plugin":"highlighjs","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":400},
|
||
copy: {
|
||
success: '复制成功',
|
||
error: '复制错误',
|
||
noSupport: '浏览器不支持'
|
||
},
|
||
relativeDate: {
|
||
homepage: true,
|
||
post: true
|
||
},
|
||
runtime: '天',
|
||
dateSuffix: {
|
||
just: '刚刚',
|
||
min: '分钟前',
|
||
hour: '小时前',
|
||
day: '天前',
|
||
month: '个月前'
|
||
},
|
||
copyright: undefined,
|
||
lightbox: 'mediumZoom',
|
||
Snackbar: {"chs_to_cht":"你已切换为繁体","cht_to_chs":"你已切换为简体","day_to_night":"你已切换为深色模式","night_to_day":"你已切换为浅色模式","bgLight":"#006650","bgDark":"#006650","position":"top-center"},
|
||
source: {
|
||
justifiedGallery: {
|
||
js: 'https://fastly.jsdelivr.net/npm/flickr-justified-gallery/dist/fjGallery.min.js',
|
||
css: 'https://fastly.jsdelivr.net/npm/flickr-justified-gallery/dist/fjGallery.min.css'
|
||
}
|
||
},
|
||
isPhotoFigcaption: false,
|
||
islazyload: false,
|
||
isAnchor: true,
|
||
percent: {
|
||
toc: true,
|
||
rightside: false,
|
||
},
|
||
autoDarkmode: true
|
||
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
|
||
title: '微信登录',
|
||
isPost: true,
|
||
isHome: false,
|
||
isHighlightShrink: false,
|
||
isToc: true,
|
||
postUpdate: '2023-09-12 07:36:50'
|
||
}</script><noscript><style type="text/css">
|
||
#nav {
|
||
opacity: 1
|
||
}
|
||
.justified-gallery img {
|
||
opacity: 1
|
||
}
|
||
|
||
#recent-posts time,
|
||
#post-meta time {
|
||
display: inline !important
|
||
}
|
||
</style></noscript><script>(win=>{
|
||
win.saveToLocal = {
|
||
set: function setWithExpiry(key, value, ttl) {
|
||
if (ttl === 0) return
|
||
const now = new Date()
|
||
const expiryDay = ttl * 86400000
|
||
const item = {
|
||
value: value,
|
||
expiry: now.getTime() + expiryDay,
|
||
}
|
||
localStorage.setItem(key, JSON.stringify(item))
|
||
},
|
||
|
||
get: function getWithExpiry(key) {
|
||
const itemStr = localStorage.getItem(key)
|
||
|
||
if (!itemStr) {
|
||
return undefined
|
||
}
|
||
const item = JSON.parse(itemStr)
|
||
const now = new Date()
|
||
|
||
if (now.getTime() > item.expiry) {
|
||
localStorage.removeItem(key)
|
||
return undefined
|
||
}
|
||
return item.value
|
||
}
|
||
}
|
||
|
||
win.getScript = url => new Promise((resolve, reject) => {
|
||
const script = document.createElement('script')
|
||
script.src = url
|
||
script.async = true
|
||
script.onerror = reject
|
||
script.onload = script.onreadystatechange = function() {
|
||
const loadState = this.readyState
|
||
if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
|
||
script.onload = script.onreadystatechange = null
|
||
resolve()
|
||
}
|
||
document.head.appendChild(script)
|
||
})
|
||
|
||
win.getCSS = (url,id = false) => new Promise((resolve, reject) => {
|
||
const link = document.createElement('link')
|
||
link.rel = 'stylesheet'
|
||
link.href = url
|
||
if (id) link.id = id
|
||
link.onerror = reject
|
||
link.onload = link.onreadystatechange = function() {
|
||
const loadState = this.readyState
|
||
if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
|
||
link.onload = link.onreadystatechange = null
|
||
resolve()
|
||
}
|
||
document.head.appendChild(link)
|
||
})
|
||
|
||
win.activateDarkMode = function () {
|
||
document.documentElement.setAttribute('data-theme', 'dark')
|
||
if (document.querySelector('meta[name="theme-color"]') !== null) {
|
||
document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
|
||
}
|
||
}
|
||
win.activateLightMode = function () {
|
||
document.documentElement.setAttribute('data-theme', 'light')
|
||
if (document.querySelector('meta[name="theme-color"]') !== null) {
|
||
document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff')
|
||
}
|
||
}
|
||
const t = saveToLocal.get('theme')
|
||
|
||
const isDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches
|
||
const isLightMode = window.matchMedia('(prefers-color-scheme: light)').matches
|
||
const isNotSpecified = window.matchMedia('(prefers-color-scheme: no-preference)').matches
|
||
const hasNoSupport = !isDarkMode && !isLightMode && !isNotSpecified
|
||
|
||
if (t === undefined) {
|
||
if (isLightMode) activateLightMode()
|
||
else if (isDarkMode) activateDarkMode()
|
||
else if (isNotSpecified || hasNoSupport) {
|
||
const now = new Date()
|
||
const hour = now.getHours()
|
||
const isNight = hour <= 8 || hour >= 22
|
||
isNight ? activateDarkMode() : activateLightMode()
|
||
}
|
||
window.matchMedia('(prefers-color-scheme: dark)').addListener(function (e) {
|
||
if (saveToLocal.get('theme') === undefined) {
|
||
e.matches ? activateDarkMode() : activateLightMode()
|
||
}
|
||
})
|
||
} else if (t === 'light') activateLightMode()
|
||
else activateDarkMode()
|
||
|
||
const asideStatus = saveToLocal.get('aside-status')
|
||
if (asideStatus !== undefined) {
|
||
if (asideStatus === 'hide') {
|
||
document.documentElement.classList.add('hide-aside')
|
||
} else {
|
||
document.documentElement.classList.remove('hide-aside')
|
||
}
|
||
}
|
||
|
||
const detectApple = () => {
|
||
if(/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)){
|
||
document.documentElement.classList.add('apple')
|
||
}
|
||
}
|
||
detectApple()
|
||
})(window)</script><script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script><script type="text/javascript" src ="/js/welcome.js" ></script><script src="/js/sweetalert.js"></script><link rel="stylesheet" href="/css/sweetalert.css"><!-- hexo injector head_end start --><link rel="stylesheet" href="https://npm.elemecdn.com/hexo-butterfly-swiper/lib/swiper.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="https://npm.elemecdn.com/hexo-butterfly-swiper/lib/swiperstyle.css" media="print" onload="this.media='all'"><!-- hexo injector head_end end --><meta name="generator" content="Hexo 6.3.0"></head><body><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img is-center"><img src="/img/avatar.jpg" onerror="onerror=null;src='/img/loading.gif'" alt="avatar"/></div><div class="sidebar-site-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">60</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">39</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">10</div></a></div><br/><div class="menus_items"><div class="menus_item"><a class="site-page" target="_blank" rel="noopener" href="https://www.tutorialspoint.com/compile_java8_online.php"><i class="fa-fw fas fa-code"></i><span> 代码</span></a></div><div class="menus_item"><a class="site-page" href="/notice/"><i class="fa-fw fas fa-stream"></i><span> 公告</span></a></div><div class="menus_item"><a class="site-page" href="/website/"><i class="fa-fw fas fa-list"></i><span> 网址</span></a></div><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 主页</span></a></div></div></div></div><div class="post" id="body-wrap"><header class="not-top-img" id="page-header"><nav id="nav"><span id="blog-info"><a href="/" title="The Blog"><img class="site-icon" src="/img/logo.png"/><span class="site-name">The Blog</span></a></span><div id="menus"><div id="search-button"><a class="site-page social-icon search" href="javascript:void(0);"><i class="fas fa-search fa-fw"></i><span> 搜索</span></a></div><div class="menus_items"><div class="menus_item"><a class="site-page" target="_blank" rel="noopener" href="https://www.tutorialspoint.com/compile_java8_online.php"><i class="fa-fw fas fa-code"></i><span> 代码</span></a></div><div class="menus_item"><a class="site-page" href="/notice/"><i class="fa-fw fas fa-stream"></i><span> 公告</span></a></div><div class="menus_item"><a class="site-page" href="/website/"><i class="fa-fw fas fa-list"></i><span> 网址</span></a></div><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 主页</span></a></div></div><div id="toggle-menu"><a class="site-page" href="javascript:void(0);"><i class="fas fa-bars fa-fw"></i></a></div></div></nav></header><main class="layout" id="content-inner"><div id="post"><div id="post-info"><h1 class="post-title">微信登录</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><i class="far fa-calendar-alt fa-fw post-meta-icon"></i><span class="post-meta-label">发表于</span><time class="post-meta-date-created" datetime="2023-04-20T14:02:22.000Z" title="发表于 2023-04-20 22:02:22">2023-04-20</time><span class="post-meta-separator">|</span><i class="fas fa-history fa-fw post-meta-icon"></i><span class="post-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2023-09-11T23:36:50.000Z" title="更新于 2023-09-12 07:36:50">2023-09-12</time></span><span class="post-meta-categories"><span class="post-meta-separator">|</span><i class="fas fa-inbox fa-fw post-meta-icon"></i><a class="post-meta-categories" href="/categories/%E5%90%8E%E7%AB%AF/">后端</a></span></div><div class="meta-secondline"><span class="post-meta-separator">|</span><span class="post-meta-wordcount"><i class="far fa-file-word fa-fw post-meta-icon"></i><span class="post-meta-label">字数总计:</span><span class="word-count">4k</span><span class="post-meta-separator">|</span><i class="far fa-clock fa-fw post-meta-icon"></i><span class="post-meta-label">阅读时长:</span><span>18分钟</span></span><span class="post-meta-separator">|</span><span class="post-meta-pv-cv" id="" data-flag-title="微信登录"><i class="far fa-eye fa-fw post-meta-icon"></i><span class="post-meta-label">阅读量:</span><span id="busuanzi_value_page_pv"><i class="fa-solid fa-spinner fa-spin"></i></span></span></div></div></div><article class="post-content" id="article-container"><h2 id="1、OAuth2"><a href="#1、OAuth2" class="headerlink" title="1、OAuth2"></a>1、OAuth2</h2><p>微信登录使用了OAuth2解决方案</p>
|
||
<h3 id="1-1-OAuth2解决什么问题"><a href="#1-1-OAuth2解决什么问题" class="headerlink" title="1.1 OAuth2解决什么问题"></a>1.1 OAuth2解决什么问题</h3><h4 id="1-1-1-开放系统间授权"><a href="#1-1-1-开放系统间授权" class="headerlink" title="1.1.1 开放系统间授权"></a>1.1.1 开放系统间授权</h4><p>照片拥有者想要在云冲印服务上打印照片,云冲印服务需要访问云存储服务上的资源</p>
|
||
<p><img src="/pictures/clip_image002.jpg" alt="IMG_256"></p>
|
||
<h4 id="1-1-2图例"><a href="#1-1-2图例" class="headerlink" title="1.1.2图例"></a>1.1.2图例</h4><p>资源拥有者:照片拥有者</p>
|
||
<p>客户应用:云冲印</p>
|
||
<p>受保护的资源:照片</p>
|
||
<p><img src="/pictures/clip_image004.jpg" alt="IMG_256"></p>
|
||
<h4 id="1-1-3方式一:用户名密码复制"><a href="#1-1-3方式一:用户名密码复制" class="headerlink" title="1.1.3方式一:用户名密码复制"></a>1.1.3方式一:用户名密码复制</h4><p><img src="/pictures/clip_image006.jpg" alt="IMG_258"></p>
|
||
<p>用户将自己的”云存储”服务的用户名和密码,告诉”云冲印”,后者就可以读取用户的照片了。这样的做法有以下几个严重的缺点。</p>
|
||
<p>(1)”云冲印”为了后续的服务,会保存用户的密码,这样很不安全。</p>
|
||
<p>(2)Google不得不部署密码登录,而我们知道,单纯的密码登录并不安全。</p>
|
||
<p>(3)”云冲印”拥有了获取用户储存在Google所有资料的权力,用户没法限制”云冲印”获得授权的范围和有效期。</p>
|
||
<p>(4)用户只有修改密码,才能收回赋予”云冲印”的权力。但是这样做,会使得其他所有获得用户授权的第三方应用程序全部失效。</p>
|
||
<p>(5)只要有一个第三方应用程序被破解,就会导致用户密码泄漏,以及所有被密码保护的数据泄漏。</p>
|
||
<p><strong>总结:</strong></p>
|
||
<p>将受保护的资源中的用户名和密码存储在客户应用的服务器上,使用时直接使用这个用户名和密码登录</p>
|
||
<p>适用于同一公司内部的多个系统,不适用于不受信的第三方应用</p>
|
||
<h4 id="1-1-4方式二:通用开发者key"><a href="#1-1-4方式二:通用开发者key" class="headerlink" title="1.1.4方式二:通用开发者key"></a>1.1.4方式二:通用开发者key</h4><p>适用于合作商或者授信的不同业务部门之间</p>
|
||
<p><img src="/pictures/clip_image008.jpg" alt="IMG_259"></p>
|
||
<h4 id="1-1-5方式三:颁发令牌"><a href="#1-1-5方式三:颁发令牌" class="headerlink" title="1.1.5方式三:颁发令牌"></a>1.1.5方式三:颁发令牌</h4><p>接近OAuth2方式,需要考虑如何管理令牌、颁发令牌、吊销令牌,需要统一的协议,因此就有了OAuth2协议</p>
|
||
<p><img src="/pictures/clip_image010.jpg" alt="IMG_256"></p>
|
||
<p><strong>令牌类比仆从钥匙</strong></p>
|
||
<p><img src="/pictures/clip_image012.jpg" alt="IMG_256"></p>
|
||
<h3 id="1-2-OAuth2最简向导"><a href="#1-2-OAuth2最简向导" class="headerlink" title="1.2 OAuth2最简向导"></a>1.2 OAuth2最简向导</h3><h4 id="1-2-1-OAuth主要角色"><a href="#1-2-1-OAuth主要角色" class="headerlink" title="1.2.1 OAuth主要角色"></a>1.2.1 OAuth主要角色</h4><p><img src="/pictures/clip_image014.jpg" alt="IMG_256"></p>
|
||
<h4 id="1-2-2最简向导"><a href="#1-2-2最简向导" class="headerlink" title="1.2.2最简向导"></a>1.2.2最简向导</h4><p>川崎高彦:OAuth2领域专家,开发了一个OAuth2 sass服务,OAuth2 as Service,并且做成了一个公司</p>
|
||
<p>在融资的过程中为了向投资人解释OAuth2是什么,于是写了一篇文章,《OAuth2最简向导》</p>
|
||
<h3 id="1-3-OAuth2的应用"><a href="#1-3-OAuth2的应用" class="headerlink" title="1.3 OAuth2的应用"></a>1.3 OAuth2的应用</h3><h4 id="1-3-1-微服务安全"><a href="#1-3-1-微服务安全" class="headerlink" title="1.3.1 微服务安全"></a>1.3.1 微服务安全</h4><p>现代微服务中系统微服务化以及应用的形态和设备类型增多,不能用传统的登录方式</p>
|
||
<p>核心的技术不是用户名和密码,而是token,由AuthServer颁发token,用户使用token进行登录</p>
|
||
<p><img src="/pictures/clip_image016.jpg" alt="IMG_256"></p>
|
||
<h4 id="1-3-2-社交登录"><a href="#1-3-2-社交登录" class="headerlink" title="1.3.2 社交登录"></a>1.3.2 社交登录</h4><p><img src="/pictures/clip_image018.jpg"></p>
|
||
<h2 id="2、微信登录介绍"><a href="#2、微信登录介绍" class="headerlink" title="2、微信登录介绍"></a>2、微信登录介绍</h2><h3 id="2-1-前期准备"><a href="#2-1-前期准备" class="headerlink" title="2.1 前期准备"></a>2.1 前期准备</h3><p>1、注册</p>
|
||
<p>微信开放平台:<a target="_blank" rel="noopener" href="https://open.weixin.qq.com/">https://open.weixin.qq.com</a></p>
|
||
<p>2、邮箱激活</p>
|
||
<p>3、完善开发者资料</p>
|
||
<p>4、开发者资质认证</p>
|
||
<p>准备营业执照,1-2个工作日审批、300元</p>
|
||
<p>5、创建网站应用</p>
|
||
<p>提交审核,7个工作日审批</p>
|
||
<p>6、内网穿透</p>
|
||
<p>ngrok的使用</p>
|
||
<h3 id="2-2-授权流程"><a href="#2-2-授权流程" class="headerlink" title="2.2 授权流程"></a>2.2 授权流程</h3><p>参考文档:<a target="_blank" rel="noopener" href="https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419316505&token=e547653f995d8f402704d5cb2945177dc8aa4e7e&lang=zh_CN">https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419316505&token=e547653f995d8f402704d5cb2945177dc8aa4e7e&lang=zh_CN</a></p>
|
||
<p><strong>获取access_token时序图</strong></p>
|
||
<p><img src="/pictures/clip_image002.gif" alt="IMG_256"></p>
|
||
<p>第一步:请求CODE(生成授权URL)</p>
|
||
<p>第二步:通过code获取access_token(开发回调URL)</p>
|
||
<h2 id="3、使用教程"><a href="#3、使用教程" class="headerlink" title="3、使用教程"></a>3、使用教程</h2><p>由于微信登录需要企业用户才能注册,这里我们使用的是尚硅谷的密钥</p>
|
||
<p>当前项目的启动端口设置为 8160 才可以获取到登录的二维码</p>
|
||
<h3 id="3-1-配置文件中添加配置"><a href="#3-1-配置文件中添加配置" class="headerlink" title="3.1 配置文件中添加配置"></a>3.1 配置文件中添加配置</h3><figure class="highlight properties"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 微信开放平台appid</span></span><br><span class="line"><span class="attr">wx.open.app_id</span>=<span class="string">wxed9954c01bb89b47</span></span><br><span class="line"><span class="comment"># 微信开放平台appsecret</span></span><br><span class="line"><span class="attr">wx.open.app_secret</span>=<span class="string">a7482517235173ddb4083788de60b90e</span></span><br><span class="line"><span class="comment">#回调的地址</span></span><br><span class="line"><span class="attr">wx.open.redirect_url</span>=<span class="string">http://localhost:8160/api/ucenter/wx/callback</span></span><br><span class="line"><span class="comment">#前端项目的地址</span></span><br><span class="line"><span class="attr">yygh.baseUrl</span>=<span class="string">http://localhost:3000</span></span><br></pre></td></tr></table></figure>
|
||
|
||
<h3 id="3-2-编写配置类读取配置文件中的值"><a href="#3-2-编写配置类读取配置文件中的值" class="headerlink" title="3.2 编写配置类读取配置文件中的值"></a>3.2 编写配置类读取配置文件中的值</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.InitializingBean;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Value;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Component;</span><br><span class="line"></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ConstantPropertiesUtil</span> <span class="keyword">implements</span> <span class="title class_">InitializingBean</span> {</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Value("${wx.open.app_id}")</span></span><br><span class="line"> <span class="keyword">private</span> String appId;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Value("${wx.open.app_secret}")</span></span><br><span class="line"> <span class="keyword">private</span> String appSecret;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Value("${wx.open.redirect_url}")</span></span><br><span class="line"> <span class="keyword">private</span> String redirectUrl;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Value("${yygh.baseUrl}")</span></span><br><span class="line"> <span class="keyword">private</span> String yyghBaseUrl;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> String WX_OPEN_APP_ID;</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> String WX_OPEN_APP_SECRET;</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> String WX_OPEN_REDIRECT_URL;</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> String YYGH_BASE_URL;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">afterPropertiesSet</span><span class="params">()</span> <span class="keyword">throws</span> Exception {</span><br><span class="line"> WX_OPEN_APP_ID = appId;</span><br><span class="line"> WX_OPEN_APP_SECRET = appSecret;</span><br><span class="line"> WX_OPEN_REDIRECT_URL = redirectUrl;</span><br><span class="line"> YYGH_BASE_URL = yyghBaseUrl;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
|
||
|
||
<h3 id="3-3-生成二维码和扫描二维码之后的回调操作"><a href="#3-3-生成二维码和扫描二维码之后的回调操作" class="headerlink" title="3.3 生成二维码和扫描二维码之后的回调操作"></a>3.3 生成二维码和扫描二维码之后的回调操作</h3><h4 id="3-3-1-生成二维码"><a href="#3-3-1-生成二维码" class="headerlink" title="3.3.1 生成二维码"></a>3.3.1 生成二维码</h4><p>生成内嵌的二维码</p>
|
||
<p>返回给前端的相关参数</p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th align="left">参数</th>
|
||
<th align="left">是否必须</th>
|
||
<th align="left">说明</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody><tr>
|
||
<td align="left">self_redirect</td>
|
||
<td align="left">否</td>
|
||
<td align="left">true:手机点击确认登录后可以在 iframe 内跳转到 redirect_uri,false:手机点击确认登录后可以在 top window 跳转到 redirect_uri。默认为 false。</td>
|
||
</tr>
|
||
<tr>
|
||
<td align="left">id</td>
|
||
<td align="left">是</td>
|
||
<td align="left">第三方页面显示二维码的容器id</td>
|
||
</tr>
|
||
<tr>
|
||
<td align="left">appid</td>
|
||
<td align="left">是</td>
|
||
<td align="left">应用唯一标识,在微信开放平台提交应用审核通过后获得</td>
|
||
</tr>
|
||
<tr>
|
||
<td align="left">scope</td>
|
||
<td align="left">是</td>
|
||
<td align="left">应用授权作用域,拥有多个作用域用逗号(,)分隔,网页应用目前仅填写snsapi_login即可</td>
|
||
</tr>
|
||
<tr>
|
||
<td align="left">redirect_uri</td>
|
||
<td align="left">是</td>
|
||
<td align="left">重定向地址,需要进行UrlEncode</td>
|
||
</tr>
|
||
<tr>
|
||
<td align="left">state</td>
|
||
<td align="left">否</td>
|
||
<td align="left">用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验</td>
|
||
</tr>
|
||
<tr>
|
||
<td align="left">style</td>
|
||
<td align="left">否</td>
|
||
<td align="left">提供”black”、”white”可选,默认为黑色文字描述。详见文档底部FAQ</td>
|
||
</tr>
|
||
<tr>
|
||
<td align="left">href</td>
|
||
<td align="left">否</td>
|
||
<td align="left">自定义样式链接,第三方可根据实际需求覆盖默认样式。详见文档底部FAQ</td>
|
||
</tr>
|
||
</tbody></table>
|
||
<p>生成扫描二维码的后端部分</p>
|
||
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> com.atguigu.yygh.common.result.Result;</span><br><span class="line"><span class="keyword">import</span> com.atguigu.yygh.user.utils.ConstantPropertiesUtil;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Controller;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.CrossOrigin;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.GetMapping;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.RequestMapping;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.ResponseBody;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.io.UnsupportedEncodingException;</span><br><span class="line"><span class="keyword">import</span> java.net.URLEncoder;</span><br><span class="line"><span class="keyword">import</span> java.util.HashMap;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> GongChangjiang</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@version</span> 1.0</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Date</span> 2023/4/20</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span> 微信登录的控制器方法</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Controller</span></span><br><span class="line"><span class="meta">@RequestMapping("/api/ucenter/wx")</span></span><br><span class="line"><span class="meta">@CrossOrigin</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">WxController</span> {</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 生成微信扫描二维码</span></span><br><span class="line"><span class="comment"> * 返回给前端一些生成二维码的参数</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@GetMapping("/getLoginParameters")</span></span><br><span class="line"> <span class="meta">@ResponseBody</span></span><br><span class="line"> <span class="keyword">public</span> Result <span class="title function_">getLoginParameters</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> HashMap<String, Object> map = <span class="keyword">new</span> <span class="title class_">HashMap</span><>();</span><br><span class="line"> map.put(<span class="string">"appid"</span>, ConstantPropertiesUtil.WX_OPEN_APP_ID);</span><br><span class="line"> map.put(<span class="string">"scope"</span>, <span class="string">"snsapi_login"</span>);</span><br><span class="line"> map.put(<span class="string">"redirect_uri"</span>, URLEncoder.encode(ConstantPropertiesUtil.WX_OPEN_REDIRECT_URL, <span class="string">"utf-8"</span>));</span><br><span class="line"> map.put(<span class="string">"state"</span>, System.currentTimeMillis() + <span class="string">""</span>);<span class="comment">//原样返回,可以没有</span></span><br><span class="line"> <span class="keyword">return</span> Result.ok(map);</span><br><span class="line"> } <span class="keyword">catch</span> (UnsupportedEncodingException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> <span class="keyword">return</span> Result.fail();</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
|
||
|
||
<p>生成扫描二维码的前端部分</p>
|
||
<p>JS部分</p>
|
||
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> request <span class="keyword">from</span> <span class="string">'@/utils/request'</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> {</span><br><span class="line"> <span class="comment">//获取生成二维码需要的参数信息</span></span><br><span class="line"> <span class="title function_">getLoginParam</span>(<span class="params"></span>) {</span><br><span class="line"> <span class="keyword">return</span> <span class="title function_">request</span>({</span><br><span class="line"> <span class="attr">url</span>: <span class="string">`/api/ucenter/wx/getLoginParam`</span>,</span><br><span class="line"> <span class="attr">method</span>: <span class="string">'get'</span></span><br><span class="line"> })</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
|
||
|
||
<p>引入api</p>
|
||
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> weixinApi <span class="keyword">from</span> <span class="string">"@/api/weixin"</span>;</span><br></pre></td></tr></table></figure>
|
||
|
||
<p>在mounted()方法中初始化微信js</p>
|
||
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="title function_">mounted</span>(<span class="params"></span>) {</span><br><span class="line"> <span class="comment">//初始化微信js</span></span><br><span class="line"> <span class="keyword">const</span> script = <span class="variable language_">document</span>.<span class="title function_">createElement</span>(<span class="string">'script'</span>)</span><br><span class="line"> script.<span class="property">type</span> = <span class="string">'text/javascript'</span></span><br><span class="line"> script.<span class="property">src</span> = <span class="string">'https://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js'</span></span><br><span class="line"> <span class="variable language_">document</span>.<span class="property">body</span>.<span class="title function_">appendChild</span>(script)</span><br><span class="line"> },</span><br></pre></td></tr></table></figure>
|
||
|
||
<p>在页面中微信登录按钮绑定的是weixinLogin()点击事件,所以我们要在这个方法中初始化对象</p>
|
||
<p>向后端发起请求获取生成二维码需要的参数信息</p>
|
||
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">weixinLogin() {</span><br><span class="line"> weixinApi.getLoginParam().then((response) => {</span><br><span class="line"> <span class="type">var</span> <span class="variable">obj</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">WxLogin</span>({</span><br><span class="line"> self_redirect: <span class="literal">true</span>,</span><br><span class="line"> id: <span class="string">"weixinLogin"</span>, <span class="comment">// 需要显示的容器id <div id="weixinLogin"></div></span></span><br><span class="line"> appid: response.data.appid, <span class="comment">// appid</span></span><br><span class="line"> scope: response.data.scope, <span class="comment">// 网页默认即可</span></span><br><span class="line"> redirect_uri: response.data.redirectUri, <span class="comment">// 授权成功后回调的url</span></span><br><span class="line"> state: response.data.state, <span class="comment">// 可设置为简单的随机数加session用来校验</span></span><br><span class="line"> style: <span class="string">"black"</span>, <span class="comment">//。二维码的样式, 提供"black"、"white"可选</span></span><br><span class="line"> href: <span class="string">""</span>, <span class="comment">// 外部css文件url,需要https</span></span><br><span class="line"> });</span><br><span class="line"> });</span><br><span class="line"> },</span><br></pre></td></tr></table></figure>
|
||
|
||
<p>点击微信登录之后,页面上的效果</p>
|
||
<p><img src="/pictures/image-20230421203717902.png" alt="image-20230421203717902"></p>
|
||
<h4 id="3-3-2-处理用户扫描成功之后的回调"><a href="#3-3-2-处理用户扫描成功之后的回调" class="headerlink" title="3.3.2 处理用户扫描成功之后的回调"></a>3.3.2 处理用户扫描成功之后的回调</h4><p>实现的思路:</p>
|
||
<p>用户扫描二维码 -> 点击确认 -> 会执行回调请求(请求配置文件中这个地址wx.open.redirect_url=<a target="_blank" rel="noopener" href="http://localhost:8160/api/ucenter/wx/callback">http://localhost:8160/api/ucenter/wx/callback</a>) -> 获取回调请求中携带的参数,再根据参数获取扫描用户的信息,执行相关的操作</p>
|
||
<p>扫描成功之后发起如下的请求:</p>
|
||
<p><img src="/pictures/image-20230421205258647.png" alt="image-20230421205258647"></p>
|
||
<p><img src="/pictures/image-20230421210454720.png" alt="image-20230421210454720"></p>
|
||
<p>引入httpclient(不依赖浏览器发起请求)依赖</p>
|
||
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">dependency</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">groupId</span>></span>org.apache.httpcomponents<span class="tag"></<span class="name">groupId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">artifactId</span>></span>httpclient<span class="tag"></<span class="name">artifactId</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">version</span>></span>4.5.1<span class="tag"></<span class="name">version</span>></span></span><br><span class="line"><span class="tag"></<span class="name">dependency</span>></span></span><br></pre></td></tr></table></figure>
|
||
|
||
<p>导入HttpClientUtils工具类</p>
|
||
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br><span class="line">294</span><br><span class="line">295</span><br><span class="line">296</span><br><span class="line">297</span><br><span class="line">298</span><br><span class="line">299</span><br><span class="line">300</span><br><span class="line">301</span><br><span class="line">302</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> org.apache.commons.io.IOUtils;</span><br><span class="line"><span class="keyword">import</span> org.apache.commons.lang.StringUtils;</span><br><span class="line"><span class="keyword">import</span> org.apache.http.Consts;</span><br><span class="line"><span class="keyword">import</span> org.apache.http.HttpEntity;</span><br><span class="line"><span class="keyword">import</span> org.apache.http.HttpResponse;</span><br><span class="line"><span class="keyword">import</span> org.apache.http.NameValuePair;</span><br><span class="line"><span class="keyword">import</span> org.apache.http.client.HttpClient;</span><br><span class="line"><span class="keyword">import</span> org.apache.http.client.config.RequestConfig;</span><br><span class="line"><span class="keyword">import</span> org.apache.http.client.config.RequestConfig.Builder;</span><br><span class="line"><span class="keyword">import</span> org.apache.http.client.entity.UrlEncodedFormEntity;</span><br><span class="line"><span class="keyword">import</span> org.apache.http.client.methods.HttpGet;</span><br><span class="line"><span class="keyword">import</span> org.apache.http.client.methods.HttpPost;</span><br><span class="line"><span class="keyword">import</span> org.apache.http.conn.ConnectTimeoutException;</span><br><span class="line"><span class="keyword">import</span> org.apache.http.conn.ssl.SSLConnectionSocketFactory;</span><br><span class="line"><span class="keyword">import</span> org.apache.http.conn.ssl.SSLContextBuilder;</span><br><span class="line"><span class="keyword">import</span> org.apache.http.conn.ssl.TrustStrategy;</span><br><span class="line"><span class="keyword">import</span> org.apache.http.conn.ssl.X509HostnameVerifier;</span><br><span class="line"><span class="keyword">import</span> org.apache.http.entity.ContentType;</span><br><span class="line"><span class="keyword">import</span> org.apache.http.entity.StringEntity;</span><br><span class="line"><span class="keyword">import</span> org.apache.http.impl.client.CloseableHttpClient;</span><br><span class="line"><span class="keyword">import</span> org.apache.http.impl.client.HttpClients;</span><br><span class="line"><span class="keyword">import</span> org.apache.http.impl.conn.PoolingHttpClientConnectionManager;</span><br><span class="line"><span class="keyword">import</span> org.apache.http.message.BasicNameValuePair;</span><br><span class="line"><span class="keyword">import</span> javax.net.ssl.SSLContext;</span><br><span class="line"><span class="keyword">import</span> javax.net.ssl.SSLException;</span><br><span class="line"><span class="keyword">import</span> javax.net.ssl.SSLSession;</span><br><span class="line"><span class="keyword">import</span> javax.net.ssl.SSLSocket;</span><br><span class="line"><span class="keyword">import</span> java.io.IOException;</span><br><span class="line"><span class="keyword">import</span> java.net.SocketTimeoutException;</span><br><span class="line"><span class="keyword">import</span> java.security.GeneralSecurityException;</span><br><span class="line"><span class="keyword">import</span> java.security.cert.CertificateException;</span><br><span class="line"><span class="keyword">import</span> java.security.cert.X509Certificate;</span><br><span class="line"><span class="keyword">import</span> java.util.ArrayList;</span><br><span class="line"><span class="keyword">import</span> java.util.List;</span><br><span class="line"><span class="keyword">import</span> java.util.Map;</span><br><span class="line"><span class="keyword">import</span> java.util.Map.Entry;</span><br><span class="line"><span class="keyword">import</span> java.util.Set;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> GongChangjiang</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@version</span> 1.0</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Date</span> 2023/4/21</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">HttpClientUtils</span> {</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">int</span> connTimeout=<span class="number">10000</span>;</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">int</span> readTimeout=<span class="number">10000</span>;</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">final</span> String charset=<span class="string">"UTF-8"</span>;</span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="type">HttpClient</span> <span class="variable">client</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">static</span> {</span><br><span class="line"> <span class="type">PoolingHttpClientConnectionManager</span> <span class="variable">cm</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">PoolingHttpClientConnectionManager</span>();</span><br><span class="line"> cm.setMaxTotal(<span class="number">128</span>);</span><br><span class="line"> cm.setDefaultMaxPerRoute(<span class="number">128</span>);</span><br><span class="line"> client = HttpClients.custom().setConnectionManager(cm).build();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> String <span class="title function_">postParameters</span><span class="params">(String url, String parameterStr)</span> <span class="keyword">throws</span> ConnectTimeoutException, SocketTimeoutException, Exception{</span><br><span class="line"> <span class="keyword">return</span> post(url,parameterStr,<span class="string">"application/x-www-form-urlencoded"</span>,charset,connTimeout,readTimeout);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> String <span class="title function_">postParameters</span><span class="params">(String url, String parameterStr,String charset, Integer connTimeout, Integer readTimeout)</span> <span class="keyword">throws</span> ConnectTimeoutException, SocketTimeoutException, Exception{</span><br><span class="line"> <span class="keyword">return</span> post(url,parameterStr,<span class="string">"application/x-www-form-urlencoded"</span>,charset,connTimeout,readTimeout);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> String <span class="title function_">postParameters</span><span class="params">(String url, Map<String, String> params)</span> <span class="keyword">throws</span> ConnectTimeoutException,</span><br><span class="line"> SocketTimeoutException, Exception {</span><br><span class="line"> <span class="keyword">return</span> postForm(url, params, <span class="literal">null</span>, connTimeout, readTimeout);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> String <span class="title function_">postParameters</span><span class="params">(String url, Map<String, String> params, Integer connTimeout,Integer readTimeout)</span> <span class="keyword">throws</span> ConnectTimeoutException,</span><br><span class="line"> SocketTimeoutException, Exception {</span><br><span class="line"> <span class="keyword">return</span> postForm(url, params, <span class="literal">null</span>, connTimeout, readTimeout);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> String <span class="title function_">get</span><span class="params">(String url)</span> <span class="keyword">throws</span> Exception {</span><br><span class="line"> <span class="keyword">return</span> get(url, charset, <span class="literal">null</span>, <span class="literal">null</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> String <span class="title function_">get</span><span class="params">(String url, String charset)</span> <span class="keyword">throws</span> Exception {</span><br><span class="line"> <span class="keyword">return</span> get(url, charset, connTimeout, readTimeout);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 发送一个 Post 请求, 使用指定的字符集编码.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> url</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> body RequestBody</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> mimeType 例如 application/xml "application/x-www-form-urlencoded" a=1&b=2&c=3</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> charset 编码</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> connTimeout 建立链接超时时间,毫秒.</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> readTimeout 响应超时时间,毫秒.</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> ResponseBody, 使用指定的字符集编码.</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@throws</span> ConnectTimeoutException 建立链接超时异常</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@throws</span> SocketTimeoutException 响应超时</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@throws</span> Exception</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> String <span class="title function_">post</span><span class="params">(String url, String body, String mimeType,String charset, Integer connTimeout, Integer readTimeout)</span></span><br><span class="line"> <span class="keyword">throws</span> ConnectTimeoutException, SocketTimeoutException, Exception {</span><br><span class="line"> <span class="type">HttpClient</span> <span class="variable">client</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line"> <span class="type">HttpPost</span> <span class="variable">post</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">HttpPost</span>(url);</span><br><span class="line"> <span class="type">String</span> <span class="variable">result</span> <span class="operator">=</span> <span class="string">""</span>;</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> <span class="keyword">if</span> (StringUtils.isNotBlank(body)) {</span><br><span class="line"> <span class="type">HttpEntity</span> <span class="variable">entity</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">StringEntity</span>(body, ContentType.create(mimeType, charset));</span><br><span class="line"> post.setEntity(entity);</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">// 设置参数</span></span><br><span class="line"> <span class="type">Builder</span> <span class="variable">customReqConf</span> <span class="operator">=</span> RequestConfig.custom();</span><br><span class="line"> <span class="keyword">if</span> (connTimeout != <span class="literal">null</span>) {</span><br><span class="line"> customReqConf.setConnectTimeout(connTimeout);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (readTimeout != <span class="literal">null</span>) {</span><br><span class="line"> customReqConf.setSocketTimeout(readTimeout);</span><br><span class="line"> }</span><br><span class="line"> post.setConfig(customReqConf.build());</span><br><span class="line"></span><br><span class="line"> HttpResponse res;</span><br><span class="line"> <span class="keyword">if</span> (url.startsWith(<span class="string">"https"</span>)) {</span><br><span class="line"> <span class="comment">// 执行 Https 请求.</span></span><br><span class="line"> client = createSSLInsecureClient();</span><br><span class="line"> res = client.execute(post);</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="comment">// 执行 Http 请求.</span></span><br><span class="line"> client = HttpClientUtils.client;</span><br><span class="line"> res = client.execute(post);</span><br><span class="line"> }</span><br><span class="line"> result = IOUtils.toString(res.getEntity().getContent(), charset);</span><br><span class="line"> } <span class="keyword">finally</span> {</span><br><span class="line"> post.releaseConnection();</span><br><span class="line"> <span class="keyword">if</span> (url.startsWith(<span class="string">"https"</span>) && client != <span class="literal">null</span>&& client <span class="keyword">instanceof</span> CloseableHttpClient) {</span><br><span class="line"> ((CloseableHttpClient) client).close();</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> result;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 提交form表单</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> url</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> params</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> connTimeout</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> readTimeout</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@throws</span> ConnectTimeoutException</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@throws</span> SocketTimeoutException</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@throws</span> Exception</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> String <span class="title function_">postForm</span><span class="params">(String url, Map<String, String> params, Map<String, String> headers, Integer connTimeout,Integer readTimeout)</span> <span class="keyword">throws</span> ConnectTimeoutException,</span><br><span class="line"> SocketTimeoutException, Exception {</span><br><span class="line"></span><br><span class="line"> <span class="type">HttpClient</span> <span class="variable">client</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line"> <span class="type">HttpPost</span> <span class="variable">post</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">HttpPost</span>(url);</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> <span class="keyword">if</span> (params != <span class="literal">null</span> && !params.isEmpty()) {</span><br><span class="line"> List<NameValuePair> formParams = <span class="keyword">new</span> <span class="title class_">ArrayList</span><NameValuePair>();</span><br><span class="line"> Set<Entry<String, String>> entrySet = params.entrySet();</span><br><span class="line"> <span class="keyword">for</span> (Entry<String, String> entry : entrySet) {</span><br><span class="line"> formParams.add(<span class="keyword">new</span> <span class="title class_">BasicNameValuePair</span>(entry.getKey(), entry.getValue()));</span><br><span class="line"> }</span><br><span class="line"> <span class="type">UrlEncodedFormEntity</span> <span class="variable">entity</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">UrlEncodedFormEntity</span>(formParams, Consts.UTF_8);</span><br><span class="line"> post.setEntity(entity);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (headers != <span class="literal">null</span> && !headers.isEmpty()) {</span><br><span class="line"> <span class="keyword">for</span> (Entry<String, String> entry : headers.entrySet()) {</span><br><span class="line"> post.addHeader(entry.getKey(), entry.getValue());</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">// 设置参数</span></span><br><span class="line"> <span class="type">Builder</span> <span class="variable">customReqConf</span> <span class="operator">=</span> RequestConfig.custom();</span><br><span class="line"> <span class="keyword">if</span> (connTimeout != <span class="literal">null</span>) {</span><br><span class="line"> customReqConf.setConnectTimeout(connTimeout);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (readTimeout != <span class="literal">null</span>) {</span><br><span class="line"> customReqConf.setSocketTimeout(readTimeout);</span><br><span class="line"> }</span><br><span class="line"> post.setConfig(customReqConf.build());</span><br><span class="line"> <span class="type">HttpResponse</span> <span class="variable">res</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line"> <span class="keyword">if</span> (url.startsWith(<span class="string">"https"</span>)) {</span><br><span class="line"> <span class="comment">// 执行 Https 请求.</span></span><br><span class="line"> client = createSSLInsecureClient();</span><br><span class="line"> res = client.execute(post);</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="comment">// 执行 Http 请求.</span></span><br><span class="line"> client = HttpClientUtils.client;</span><br><span class="line"> res = client.execute(post);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> IOUtils.toString(res.getEntity().getContent(), <span class="string">"UTF-8"</span>);</span><br><span class="line"> } <span class="keyword">finally</span> {</span><br><span class="line"> post.releaseConnection();</span><br><span class="line"> <span class="keyword">if</span> (url.startsWith(<span class="string">"https"</span>) && client != <span class="literal">null</span></span><br><span class="line"> && client <span class="keyword">instanceof</span> CloseableHttpClient) {</span><br><span class="line"> ((CloseableHttpClient) client).close();</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 发送一个 GET 请求</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> String <span class="title function_">get</span><span class="params">(String url, String charset, Integer connTimeout,Integer readTimeout)</span></span><br><span class="line"> <span class="keyword">throws</span> ConnectTimeoutException,SocketTimeoutException, Exception {</span><br><span class="line"></span><br><span class="line"> <span class="type">HttpClient</span> <span class="variable">client</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line"> <span class="type">HttpGet</span> <span class="variable">get</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">HttpGet</span>(url);</span><br><span class="line"> <span class="type">String</span> <span class="variable">result</span> <span class="operator">=</span> <span class="string">""</span>;</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> <span class="comment">// 设置参数</span></span><br><span class="line"> <span class="type">Builder</span> <span class="variable">customReqConf</span> <span class="operator">=</span> RequestConfig.custom();</span><br><span class="line"> <span class="keyword">if</span> (connTimeout != <span class="literal">null</span>) {</span><br><span class="line"> customReqConf.setConnectTimeout(connTimeout);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (readTimeout != <span class="literal">null</span>) {</span><br><span class="line"> customReqConf.setSocketTimeout(readTimeout);</span><br><span class="line"> }</span><br><span class="line"> get.setConfig(customReqConf.build());</span><br><span class="line"></span><br><span class="line"> <span class="type">HttpResponse</span> <span class="variable">res</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (url.startsWith(<span class="string">"https"</span>)) {</span><br><span class="line"> <span class="comment">// 执行 Https 请求.</span></span><br><span class="line"> client = createSSLInsecureClient();</span><br><span class="line"> res = client.execute(get);</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="comment">// 执行 Http 请求.</span></span><br><span class="line"> client = HttpClientUtils.client;</span><br><span class="line"> res = client.execute(get);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> result = IOUtils.toString(res.getEntity().getContent(), charset);</span><br><span class="line"> } <span class="keyword">finally</span> {</span><br><span class="line"> get.releaseConnection();</span><br><span class="line"> <span class="keyword">if</span> (url.startsWith(<span class="string">"https"</span>) && client != <span class="literal">null</span> && client <span class="keyword">instanceof</span> CloseableHttpClient) {</span><br><span class="line"> ((CloseableHttpClient) client).close();</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> result;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 从 response 里获取 charset</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@SuppressWarnings("unused")</span></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> String <span class="title function_">getCharsetFromResponse</span><span class="params">(HttpResponse ressponse)</span> {</span><br><span class="line"> <span class="comment">// Content-Type:text/html; charset=GBK</span></span><br><span class="line"> <span class="keyword">if</span> (ressponse.getEntity() != <span class="literal">null</span> && ressponse.getEntity().getContentType() != <span class="literal">null</span> && ressponse.getEntity().getContentType().getValue() != <span class="literal">null</span>) {</span><br><span class="line"> <span class="type">String</span> <span class="variable">contentType</span> <span class="operator">=</span> ressponse.getEntity().getContentType().getValue();</span><br><span class="line"> <span class="keyword">if</span> (contentType.contains(<span class="string">"charset="</span>)) {</span><br><span class="line"> <span class="keyword">return</span> contentType.substring(contentType.indexOf(<span class="string">"charset="</span>) + <span class="number">8</span>);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 创建 SSL连接</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@throws</span> GeneralSecurityException</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> CloseableHttpClient <span class="title function_">createSSLInsecureClient</span><span class="params">()</span> <span class="keyword">throws</span> GeneralSecurityException {</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> <span class="type">SSLContext</span> <span class="variable">sslContext</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">SSLContextBuilder</span>().loadTrustMaterial(<span class="literal">null</span>, <span class="keyword">new</span> <span class="title class_">TrustStrategy</span>() {</span><br><span class="line"> <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">isTrusted</span><span class="params">(X509Certificate[] chain,String authType)</span> <span class="keyword">throws</span> CertificateException {</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"> }</span><br><span class="line"> }).build();</span><br><span class="line"></span><br><span class="line"> <span class="type">SSLConnectionSocketFactory</span> <span class="variable">sslsf</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">SSLConnectionSocketFactory</span>(sslContext, <span class="keyword">new</span> <span class="title class_">X509HostnameVerifier</span>() {</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> <span class="type">boolean</span> <span class="title function_">verify</span><span class="params">(String arg0, SSLSession arg1)</span> {</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">verify</span><span class="params">(String host, SSLSocket ssl)</span></span><br><span class="line"> <span class="keyword">throws</span> IOException {</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">verify</span><span class="params">(String host, X509Certificate cert)</span></span><br><span class="line"> <span class="keyword">throws</span> SSLException {</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Override</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">verify</span><span class="params">(String host, String[] cns,</span></span><br><span class="line"><span class="params"> String[] subjectAlts)</span> <span class="keyword">throws</span> SSLException {</span><br><span class="line"> }</span><br><span class="line"> });</span><br><span class="line"> <span class="keyword">return</span> HttpClients.custom().setSSLSocketFactory(sslsf).build();</span><br><span class="line"></span><br><span class="line"> } <span class="keyword">catch</span> (GeneralSecurityException e) {</span><br><span class="line"> <span class="keyword">throw</span> e;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>
|
||
|
||
<p>Controller</p>
|
||
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.atguigu.yygh.user.controller;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.alibaba.fastjson.JSONObject;</span><br><span class="line"><span class="keyword">import</span> com.atguigu.yygh.common.result.Result;</span><br><span class="line"><span class="keyword">import</span> com.atguigu.yygh.user.utils.ConstantPropertiesUtil;</span><br><span class="line"><span class="keyword">import</span> com.atguigu.yygh.user.utils.HttpClientUtils;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Controller;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.CrossOrigin;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.GetMapping;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.RequestMapping;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.ResponseBody;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.io.UnsupportedEncodingException;</span><br><span class="line"><span class="keyword">import</span> java.net.URLEncoder;</span><br><span class="line"><span class="keyword">import</span> java.util.HashMap;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> GongChangjiang</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@version</span> 1.0</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Date</span> 2023/4/20</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@Description</span> 微信登录的控制器方法</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Controller</span></span><br><span class="line"><span class="meta">@RequestMapping("/api/ucenter/wx")</span></span><br><span class="line"><span class="meta">@CrossOrigin</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">WxController</span> {</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 生成微信扫描二维码</span></span><br><span class="line"><span class="comment"> * 返回给前端一些生成二维码的参数</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@GetMapping("/getLoginParam")</span></span><br><span class="line"> <span class="meta">@ResponseBody</span></span><br><span class="line"> <span class="keyword">public</span> Result <span class="title function_">getLoginParameters</span><span class="params">()</span> {</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> HashMap<String, Object> map = <span class="keyword">new</span> <span class="title class_">HashMap</span><>();</span><br><span class="line"> map.put(<span class="string">"appid"</span>, ConstantPropertiesUtil.WX_OPEN_APP_ID);</span><br><span class="line"> map.put(<span class="string">"scope"</span>, <span class="string">"snsapi_login"</span>);</span><br><span class="line"> map.put(<span class="string">"redirect_uri"</span>, URLEncoder.encode(ConstantPropertiesUtil.WX_OPEN_REDIRECT_URL, <span class="string">"utf-8"</span>));</span><br><span class="line"> map.put(<span class="string">"state"</span>, System.currentTimeMillis() + <span class="string">""</span>);<span class="comment">//原样返回,可以没有</span></span><br><span class="line"> <span class="keyword">return</span> Result.ok(map);</span><br><span class="line"> } <span class="keyword">catch</span> (UnsupportedEncodingException e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> <span class="keyword">return</span> Result.fail();</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 扫描之后回调的请求中携带了相关的参数,帮助我们获取用户的信息</span></span><br><span class="line"><span class="comment"> * 登录成功之后的回调方法</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> code 临时票据</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> state 生成微信二维码之前put进去的参数 原样返回</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="meta">@GetMapping("/callback")</span></span><br><span class="line"> <span class="keyword">public</span> String <span class="title function_">callback</span><span class="params">(String code ,String state)</span>{</span><br><span class="line"> <span class="comment">//通过code、appid和app_secret去请求固定地址换取access_token</span></span><br><span class="line"> <span class="type">StringBuffer</span> <span class="variable">baseAccessTokenUrl</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">StringBuffer</span>()</span><br><span class="line"> .append(<span class="string">"https://api.weixin.qq.com/sns/oauth2/access_token"</span>) <span class="comment">//请求的固定地址</span></span><br><span class="line"> .append(<span class="string">"?appid=%s"</span>) <span class="comment">//%s占位符</span></span><br><span class="line"> .append(<span class="string">"&secret=%s"</span>)</span><br><span class="line"> .append(<span class="string">"&code=%s"</span>)</span><br><span class="line"> .append(<span class="string">"&grant_type=authorization_code"</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//拼接完整之后的地址</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">accessTokenUrl</span> <span class="operator">=</span> String.format(baseAccessTokenUrl.toString(),</span><br><span class="line"> ConstantPropertiesUtil.WX_OPEN_APP_ID,</span><br><span class="line"> ConstantPropertiesUtil.WX_OPEN_APP_SECRET,</span><br><span class="line"> code);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//使用httpclient去请求这个地址换取access_token</span></span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> <span class="type">String</span> <span class="variable">accessTokenInfo</span> <span class="operator">=</span> HttpClientUtils.get(accessTokenUrl);<span class="comment">//json格式的字符串</span></span><br><span class="line"> <span class="comment">//从这个字符串中获取openid和 access_token的值</span></span><br><span class="line"> <span class="type">JSONObject</span> <span class="variable">jsonObject</span> <span class="operator">=</span> JSONObject.parseObject(accessTokenInfo);</span><br><span class="line"> <span class="type">String</span> <span class="variable">accessToken</span> <span class="operator">=</span> jsonObject.getString(<span class="string">"access_token"</span>);</span><br><span class="line"> <span class="type">String</span> <span class="variable">openid</span> <span class="operator">=</span> jsonObject.getString(<span class="string">"openid"</span>);</span><br><span class="line"> <span class="comment">//根据access_token和openid获取微信用户的基本信息</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">baseUserInfoUrl</span> <span class="operator">=</span> <span class="string">"https://api.weixin.qq.com/sns/userinfo"</span> +</span><br><span class="line"> <span class="string">"?access_token=%s"</span> +</span><br><span class="line"> <span class="string">"&openid=%s"</span>;</span><br><span class="line"> <span class="type">String</span> <span class="variable">userInfoUrl</span> <span class="operator">=</span> String.format(baseUserInfoUrl, accessToken, openid);</span><br><span class="line"> <span class="comment">//发起请求获取用户信息</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">userInfo</span> <span class="operator">=</span> HttpClientUtils.get(userInfoUrl);<span class="comment">//json格式的字符串</span></span><br><span class="line"> <span class="type">JSONObject</span> <span class="variable">parseObject</span> <span class="operator">=</span> JSONObject.parseObject(userInfo);</span><br><span class="line"> <span class="comment">//获取具体的用户信息</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">nickname</span> <span class="operator">=</span> parseObject.getString(<span class="string">"nickname"</span>);<span class="comment">//用户昵称</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">sex</span> <span class="operator">=</span> parseObject.getString(<span class="string">"sex"</span>);<span class="comment">//性别</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">language</span> <span class="operator">=</span> parseObject.getString(<span class="string">"language"</span>);<span class="comment">//语言</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">city</span> <span class="operator">=</span> parseObject.getString(<span class="string">"city"</span>);<span class="comment">//所在城市</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">province</span> <span class="operator">=</span> parseObject.getString(<span class="string">"province"</span>);<span class="comment">//省份</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">country</span> <span class="operator">=</span> parseObject.getString(<span class="string">"country"</span>);<span class="comment">//注册国家</span></span><br><span class="line"> <span class="type">String</span> <span class="variable">headimgurl</span> <span class="operator">=</span> parseObject.getString(<span class="string">"headimgurl"</span>);<span class="comment">//头像的url地址</span></span><br><span class="line"> System.out.println(<span class="string">"昵称:"</span>+nickname+<span class="string">",性别:"</span>+sex+<span class="string">",语言:"</span>+language+<span class="string">",城市:"</span>+city+<span class="string">",省份:"</span>+province+<span class="string">",注册国家:"</span>+country+<span class="string">",头像地址:"</span>+headimgurl);</span><br><span class="line"> <span class="comment">//TODO 将扫码人的信息添加到数据库中</span></span><br><span class="line"> } <span class="keyword">catch</span> (Exception e) {</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="string">"redirect:地址信息&参数信息(用户信息或者token信息等)"</span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
</article><div class="tag_share"><div class="post-meta__tag-list"><a class="post-meta__tags" href="/tags/Java/">Java</a></div><div class="post_share"><div class="social-share" data-image="/img/5.png" data-sites="wechat,weibo,qq"></div><link rel="stylesheet" href="/cdn/css/share.min.css" media="print" onload="this.media='all'"><script src="/cdn/js/social-share.min.js" defer></script></div></div><div class="post-reward"><div class="reward-button"><i class="fas fa-qrcode"></i> 打赏</div><div class="reward-main"><ul class="reward-all"><li class="reward-item"><a href="/img/wechat.jpg" target="_blank"><img class="post-qr-code-img" src="/img/wechat.jpg" alt="微信"/></a><div class="post-qr-code-desc">微信</div></li><li class="reward-item"><a href="/img/alipay.jpg" target="_blank"><img class="post-qr-code-img" src="/img/alipay.jpg" alt="支付宝"/></a><div class="post-qr-code-desc">支付宝</div></li></ul></div></div><br/><div id="post-comment"><div class="comment-head"><div class="comment-headline"><i class="far fa-comment-alt fa-fw"></i><span> 评论</span></div></div><div class="comment-wrap"><div><div id="gitalk-container"></div></div></div></div></div><div class="aside-content" id="aside-content"><div class="card-widget card-info"><div class="is-center"><div class="avatar-img"><img src="/img/avatar.jpg" onerror="this.onerror=null;this.src='/img/loading.gif'" alt="avatar"/></div><div class="author-info__name">Jason</div><div class="author-info__description">Debug the World!</div></div><div class="card-info-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">60</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">39</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">10</div></a></div><a id="card-info-btn"><i class="fab fa-microsoft"></i><span>Ctrl + D 收藏</span></a><div class="card-info-social-icons is-center"><a class="social-icon" href="https://github.com/JasonsGong" target="_blank" title="Github"><i class="fab fa-github"></i></a><a class="social-icon" href="tencent://AddContact/?fromId=45&fromSubId=1&subcmd=all&uin=2602183349&website=www.oicqzone.com" target="_blank" title="QQ"><i class="fab fa-qq"></i></a><a class="social-icon" href="mailto:2602183349@qq.com" target="_blank" title="Email"><i class="fas fa-envelope-open-text"></i></a><a class="social-icon" href="https://github.com/JasonsGong?tab=repositories" target="_blank" title="代码仓库"><i class="fas fa-database"></i></a></div></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn fa-shake"></i><span>公告</span></div><div class="announcement_content">本网站是静态网站,更新页面资源请使用Ctrl+F5;若网站内文章对你有帮助,请使用Ctrl+D收藏该网站!</div></div><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="item-headline"><i class="fas fa-stream"></i><span>目录</span><span class="toc-percentage"></span></div><div class="toc-content is-expand"><ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#1%E3%80%81OAuth2"><span class="toc-text">1、OAuth2</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1-1-OAuth2%E8%A7%A3%E5%86%B3%E4%BB%80%E4%B9%88%E9%97%AE%E9%A2%98"><span class="toc-text">1.1 OAuth2解决什么问题</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#1-1-1-%E5%BC%80%E6%94%BE%E7%B3%BB%E7%BB%9F%E9%97%B4%E6%8E%88%E6%9D%83"><span class="toc-text">1.1.1 开放系统间授权</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#1-1-2%E5%9B%BE%E4%BE%8B"><span class="toc-text">1.1.2图例</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#1-1-3%E6%96%B9%E5%BC%8F%E4%B8%80%EF%BC%9A%E7%94%A8%E6%88%B7%E5%90%8D%E5%AF%86%E7%A0%81%E5%A4%8D%E5%88%B6"><span class="toc-text">1.1.3方式一:用户名密码复制</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#1-1-4%E6%96%B9%E5%BC%8F%E4%BA%8C%EF%BC%9A%E9%80%9A%E7%94%A8%E5%BC%80%E5%8F%91%E8%80%85key"><span class="toc-text">1.1.4方式二:通用开发者key</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#1-1-5%E6%96%B9%E5%BC%8F%E4%B8%89%EF%BC%9A%E9%A2%81%E5%8F%91%E4%BB%A4%E7%89%8C"><span class="toc-text">1.1.5方式三:颁发令牌</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#1-2-OAuth2%E6%9C%80%E7%AE%80%E5%90%91%E5%AF%BC"><span class="toc-text">1.2 OAuth2最简向导</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#1-2-1-OAuth%E4%B8%BB%E8%A6%81%E8%A7%92%E8%89%B2"><span class="toc-text">1.2.1 OAuth主要角色</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#1-2-2%E6%9C%80%E7%AE%80%E5%90%91%E5%AF%BC"><span class="toc-text">1.2.2最简向导</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#1-3-OAuth2%E7%9A%84%E5%BA%94%E7%94%A8"><span class="toc-text">1.3 OAuth2的应用</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#1-3-1-%E5%BE%AE%E6%9C%8D%E5%8A%A1%E5%AE%89%E5%85%A8"><span class="toc-text">1.3.1 微服务安全</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#1-3-2-%E7%A4%BE%E4%BA%A4%E7%99%BB%E5%BD%95"><span class="toc-text">1.3.2 社交登录</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#2%E3%80%81%E5%BE%AE%E4%BF%A1%E7%99%BB%E5%BD%95%E4%BB%8B%E7%BB%8D"><span class="toc-text">2、微信登录介绍</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#2-1-%E5%89%8D%E6%9C%9F%E5%87%86%E5%A4%87"><span class="toc-text">2.1 前期准备</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-2-%E6%8E%88%E6%9D%83%E6%B5%81%E7%A8%8B"><span class="toc-text">2.2 授权流程</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#3%E3%80%81%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B"><span class="toc-text">3、使用教程</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#3-1-%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E4%B8%AD%E6%B7%BB%E5%8A%A0%E9%85%8D%E7%BD%AE"><span class="toc-text">3.1 配置文件中添加配置</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-2-%E7%BC%96%E5%86%99%E9%85%8D%E7%BD%AE%E7%B1%BB%E8%AF%BB%E5%8F%96%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E4%B8%AD%E7%9A%84%E5%80%BC"><span class="toc-text">3.2 编写配置类读取配置文件中的值</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-3-%E7%94%9F%E6%88%90%E4%BA%8C%E7%BB%B4%E7%A0%81%E5%92%8C%E6%89%AB%E6%8F%8F%E4%BA%8C%E7%BB%B4%E7%A0%81%E4%B9%8B%E5%90%8E%E7%9A%84%E5%9B%9E%E8%B0%83%E6%93%8D%E4%BD%9C"><span class="toc-text">3.3 生成二维码和扫描二维码之后的回调操作</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#3-3-1-%E7%94%9F%E6%88%90%E4%BA%8C%E7%BB%B4%E7%A0%81"><span class="toc-text">3.3.1 生成二维码</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#3-3-2-%E5%A4%84%E7%90%86%E7%94%A8%E6%88%B7%E6%89%AB%E6%8F%8F%E6%88%90%E5%8A%9F%E4%B9%8B%E5%90%8E%E7%9A%84%E5%9B%9E%E8%B0%83"><span class="toc-text">3.3.2 处理用户扫描成功之后的回调</span></a></li></ol></li></ol></li></ol></div></div><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>最近更新</span></div><div class="aside-list"><div class="aside-list-item"><a class="thumbnail" href="/posts/8957.html" title="Linux从入门到进阶"><img src="/img/8.png" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="Linux从入门到进阶"/></a><div class="content"><a class="title" href="/posts/8957.html" title="Linux从入门到进阶">Linux从入门到进阶</a><time datetime="2024-05-10T05:31:11.691Z" title="更新于 2024-05-10 13:31:11">2024-05-10</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/posts/35630.html" title="接口测试工具"><img src="/img/2.png" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="接口测试工具"/></a><div class="content"><a class="title" href="/posts/35630.html" title="接口测试工具">接口测试工具</a><time datetime="2024-05-10T05:31:11.686Z" title="更新于 2024-05-10 13:31:11">2024-05-10</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/posts/32246.html" title="SpringBoot中整合Swagger2"><img src="/img/3.png" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="SpringBoot中整合Swagger2"/></a><div class="content"><a class="title" href="/posts/32246.html" title="SpringBoot中整合Swagger2">SpringBoot中整合Swagger2</a><time datetime="2024-05-10T05:31:11.681Z" title="更新于 2024-05-10 13:31:11">2024-05-10</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/posts/19306.html" title="Docker容器化技术"><img src="/img/1.png" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="Docker容器化技术"/></a><div class="content"><a class="title" href="/posts/19306.html" title="Docker容器化技术">Docker容器化技术</a><time datetime="2024-05-10T05:31:11.675Z" title="更新于 2024-05-10 13:31:11">2024-05-10</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/posts/20683.html" title="Linux中开发环境的搭建"><img src="/img/8.png" onerror="this.onerror=null;this.src='/img/404.jpg'" alt="Linux中开发环境的搭建"/></a><div class="content"><a class="title" href="/posts/20683.html" title="Linux中开发环境的搭建">Linux中开发环境的搭建</a><time datetime="2024-05-10T05:31:11.669Z" title="更新于 2024-05-10 13:31:11">2024-05-10</time></div></div></div></div></div></div></main><footer id="footer"><div id="footer-wrap"></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="fas fa-book-open"></i></button><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside_config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button class="close" id="mobile-toc-button" type="button" title="目录"><i class="fas fa-list-ul"></i></button><a id="to_comment" href="#post-comment" title="直达评论"><i class="fas fa-comment-alt"></i></a><button id="go-up" type="button" title="回到顶部"><span class="scroll-percent"></span><i class="fas fa-arrow-up"></i></button></div></div><div><script src="/js/utils.js"></script><script src="/js/main.js"></script><script src="/cdn/js/medium-zoom.min.js"></script><script src="/cdn/js/instantpage.min.js" type="module"></script><script src="/cdn/js/snackbar.min.js"></script><div class="js-pjax"><script>function loadGitalk () {
|
||
function initGitalk () {
|
||
var gitalk = new Gitalk(Object.assign({
|
||
clientID: '00fb27b1e484536359c2',
|
||
clientSecret: 'be41a12281c68b6e228d1a27e8d08aeb91541145',
|
||
repo: 'BlogComment',
|
||
owner: 'JasonsGong',
|
||
admin: ['JasonsGong'],
|
||
id: '706416735fc9b9e34c2d06a631491559',
|
||
updateCountCallback: commentCount
|
||
},null))
|
||
|
||
gitalk.render('gitalk-container')
|
||
}
|
||
|
||
if (typeof Gitalk === 'function') initGitalk()
|
||
else {
|
||
getCSS('/cdn/css/gitalk.min.css')
|
||
getScript('/cdn/js/gitalk.min.js').then(initGitalk)
|
||
}
|
||
}
|
||
|
||
function commentCount(n){
|
||
let isCommentCount = document.querySelector('#post-meta .gitalk-comment-count')
|
||
if (isCommentCount) {
|
||
isCommentCount.textContent= n
|
||
}
|
||
}
|
||
|
||
if ('Gitalk' === 'Gitalk' || !true) {
|
||
if (true) btf.loadComment(document.getElementById('gitalk-container'), loadGitalk)
|
||
else loadGitalk()
|
||
} else {
|
||
function loadOtherComment () {
|
||
loadGitalk()
|
||
}
|
||
}</script></div><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script><div id="local-search"><div class="search-dialog"><nav class="search-nav"><span class="search-dialog-title">搜索</span><span id="loading-status"></span><button class="search-close-button"><i class="fas fa-times"></i></button></nav><div class="is-center" id="loading-database"><i class="fas fa-spinner fa-pulse"></i><span> 数据库加载中</span></div><div class="search-wrap"><div id="local-search-input"><div class="local-search-box"><input class="local-search-box--input" placeholder="搜索文章" type="text"/></div></div><br/><div class="no-result" id="local-search-results"></div><div id="local-search-stats-wrap"></div></div></div><div id="search-mask"></div><script src="/js/search/local-search.js"></script></div></div><!-- hexo injector body_end start --><script data-pjax>
|
||
function butterfly_swiper_injector_config(){
|
||
var parent_div_git = document.getElementById('recent-posts');
|
||
var item_html = '<div class="recent-post-item" style="height: auto;width: 100%"><div class="blog-slider swiper-container-fade swiper-container-horizontal" id="swiper_container"><div class="blog-slider__wrp swiper-wrapper" style="transition-duration: 0ms;"><div class="blog-slider__item swiper-slide" style="width: 750px; opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><a class="blog-slider__img" href="posts/19306.html" alt=""><img width="48" height="48" src="/img/1.png" alt="" onerror="this.src=https://unpkg.zhimg.com/akilar-candyassets/image/loading.gif; this.onerror = null;"/></a><div class="blog-slider__content"><span class="blog-slider__code">2023-04-21</span><a class="blog-slider__title" href="posts/19306.html" alt="">Docker容器化技术</a><div class="blog-slider__text">Docker</div><a class="blog-slider__button" href="posts/19306.html" alt="">详情 </a></div></div><div class="blog-slider__item swiper-slide" style="width: 750px; opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><a class="blog-slider__img" href="posts/47003.html" alt=""><img width="48" height="48" src="/img/5.png" alt="" onerror="this.src=https://unpkg.zhimg.com/akilar-candyassets/image/loading.gif; this.onerror = null;"/></a><div class="blog-slider__content"><span class="blog-slider__code">2023-03-10</span><a class="blog-slider__title" href="posts/47003.html" alt="">常用正则表达式大全</a><div class="blog-slider__text">正则表达式</div><a class="blog-slider__button" href="posts/47003.html" alt="">详情 </a></div></div><div class="blog-slider__item swiper-slide" style="width: 750px; opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><a class="blog-slider__img" href="posts/20683.html" alt=""><img width="48" height="48" src="/img/8.png" alt="" onerror="this.src=https://unpkg.zhimg.com/akilar-candyassets/image/loading.gif; this.onerror = null;"/></a><div class="blog-slider__content"><span class="blog-slider__code">2023-06-05</span><a class="blog-slider__title" href="posts/20683.html" alt="">Linux中开发环境的搭建</a><div class="blog-slider__text">环境搭建</div><a class="blog-slider__button" href="posts/20683.html" alt="">详情 </a></div></div><div class="blog-slider__item swiper-slide" style="width: 750px; opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><a class="blog-slider__img" href="posts/63333.html" alt=""><img width="48" height="48" src="/img/10.png" alt="" onerror="this.src=https://unpkg.zhimg.com/akilar-candyassets/image/loading.gif; this.onerror = null;"/></a><div class="blog-slider__content"><span class="blog-slider__code">2023-06-03</span><a class="blog-slider__title" href="posts/63333.html" alt="">开发环境的搭建</a><div class="blog-slider__text">环境搭建</div><a class="blog-slider__button" href="posts/63333.html" alt="">详情 </a></div></div></div><div class="blog-slider__pagination swiper-pagination-clickable swiper-pagination-bullets"></div></div></div>';
|
||
if (parent_div_git !== null && typeof parent_div_git !== 'undefined') {
|
||
parent_div_git.insertAdjacentHTML("afterbegin",item_html)
|
||
}
|
||
}
|
||
var elist = 'undefined'.split(',');
|
||
var cpage = location.pathname;
|
||
var epage = 'all';
|
||
var flag = 0;
|
||
|
||
for (var i=0;i<elist.length;i++){
|
||
if (cpage.includes(elist[i])){
|
||
flag++;
|
||
}
|
||
}
|
||
|
||
if ((epage ==='all')&&(flag == 0)){
|
||
butterfly_swiper_injector_config();
|
||
}
|
||
else if (epage === cpage){
|
||
butterfly_swiper_injector_config();
|
||
}
|
||
</script><script defer src="https://npm.elemecdn.com/hexo-butterfly-swiper/lib/swiper.min.js"></script><script defer data-pjax src="https://npm.elemecdn.com/hexo-butterfly-swiper/lib/swiper_init.js"></script><!-- hexo injector body_end end --></body></html> |