JasonsGong.github.io/posts/45572.html
2024-06-14 22:00:25 +08:00

388 lines
114 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!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>2Google不得不部署密码登录而我们知道单纯的密码登录并不安全。</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&amp;t=resource/res_list&amp;verify=1&amp;id=open1419316505&amp;token=e547653f995d8f402704d5cb2945177dc8aa4e7e&amp;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> &#123;</span><br><span class="line"></span><br><span class="line"> <span class="meta">@Value(&quot;$&#123;wx.open.app_id&#125;&quot;)</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(&quot;$&#123;wx.open.app_secret&#125;&quot;)</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(&quot;$&#123;wx.open.redirect_url&#125;&quot;)</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(&quot;$&#123;yygh.baseUrl&#125;&quot;)</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 &#123;</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"> &#125;</span><br><span class="line">&#125;</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_urifalse手机点击确认登录后可以在 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(&quot;/api/ucenter/wx&quot;)</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> &#123;</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(&quot;/getLoginParameters&quot;)</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> &#123;</span><br><span class="line"> <span class="keyword">try</span> &#123;</span><br><span class="line"> HashMap&lt;String, Object&gt; map = <span class="keyword">new</span> <span class="title class_">HashMap</span>&lt;&gt;();</span><br><span class="line"> map.put(<span class="string">&quot;appid&quot;</span>, ConstantPropertiesUtil.WX_OPEN_APP_ID);</span><br><span class="line"> map.put(<span class="string">&quot;scope&quot;</span>, <span class="string">&quot;snsapi_login&quot;</span>);</span><br><span class="line"> map.put(<span class="string">&quot;redirect_uri&quot;</span>, URLEncoder.encode(ConstantPropertiesUtil.WX_OPEN_REDIRECT_URL, <span class="string">&quot;utf-8&quot;</span>));</span><br><span class="line"> map.put(<span class="string">&quot;state&quot;</span>, System.currentTimeMillis() + <span class="string">&quot;&quot;</span>);<span class="comment">//原样返回,可以没有</span></span><br><span class="line"> <span class="keyword">return</span> Result.ok(map);</span><br><span class="line"> &#125; <span class="keyword">catch</span> (UnsupportedEncodingException e) &#123;</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> <span class="keyword">return</span> Result.fail();</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</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">&#x27;@/utils/request&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line"> <span class="comment">//获取生成二维码需要的参数信息</span></span><br><span class="line"> <span class="title function_">getLoginParam</span>(<span class="params"></span>) &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="title function_">request</span>(&#123;</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">&#x27;get&#x27;</span></span><br><span class="line"> &#125;)</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</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">&quot;@/api/weixin&quot;</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>) &#123;</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">&#x27;script&#x27;</span>)</span><br><span class="line"> script.<span class="property">type</span> = <span class="string">&#x27;text/javascript&#x27;</span></span><br><span class="line"> script.<span class="property">src</span> = <span class="string">&#x27;https://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js&#x27;</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"> &#125;,</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() &#123;</span><br><span class="line"> weixinApi.getLoginParam().then((response) =&gt; &#123;</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>(&#123;</span><br><span class="line"> self_redirect: <span class="literal">true</span>,</span><br><span class="line"> id: <span class="string">&quot;weixinLogin&quot;</span>, <span class="comment">// 需要显示的容器id &lt;div id=&quot;weixinLogin&quot;&gt;&lt;/div&gt;</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">&quot;black&quot;</span>, <span class="comment">//。二维码的样式, 提供&quot;black&quot;&quot;white&quot;可选</span></span><br><span class="line"> href: <span class="string">&quot;&quot;</span>, <span class="comment">// 外部css文件url需要https</span></span><br><span class="line"> &#125;);</span><br><span class="line"> &#125;);</span><br><span class="line"> &#125;,</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>用户扫描二维码 -&gt; 点击确认 -&gt; 会执行回调请求(请求配置文件中这个地址wx.open.redirect_url&#x3D;<a target="_blank" rel="noopener" href="http://localhost:8160/api/ucenter/wx/callback">http://localhost:8160/api/ucenter/wx/callback</a>) -&gt; 获取回调请求中携带的参数,再根据参数获取扫描用户的信息,执行相关的操作</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">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.apache.httpcomponents<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>httpclient<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"> <span class="tag">&lt;<span class="name">version</span>&gt;</span>4.5.1<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</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> &#123;</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">&quot;UTF-8&quot;</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> &#123;</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"> &#125;</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&#123;</span><br><span class="line"> <span class="keyword">return</span> post(url,parameterStr,<span class="string">&quot;application/x-www-form-urlencoded&quot;</span>,charset,connTimeout,readTimeout);</span><br><span class="line"> &#125;</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&#123;</span><br><span class="line"> <span class="keyword">return</span> post(url,parameterStr,<span class="string">&quot;application/x-www-form-urlencoded&quot;</span>,charset,connTimeout,readTimeout);</span><br><span class="line"> &#125;</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&lt;String, String&gt; params)</span> <span class="keyword">throws</span> ConnectTimeoutException,</span><br><span class="line"> SocketTimeoutException, Exception &#123;</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"> &#125;</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&lt;String, String&gt; params, Integer connTimeout,Integer readTimeout)</span> <span class="keyword">throws</span> ConnectTimeoutException,</span><br><span class="line"> SocketTimeoutException, Exception &#123;</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"> &#125;</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 &#123;</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"> &#125;</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 &#123;</span><br><span class="line"> <span class="keyword">return</span> get(url, charset, connTimeout, readTimeout);</span><br><span class="line"> &#125;</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 &quot;application/x-www-form-urlencoded&quot; a=1&amp;b=2&amp;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 &#123;</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">&quot;&quot;</span>;</span><br><span class="line"> <span class="keyword">try</span> &#123;</span><br><span class="line"> <span class="keyword">if</span> (StringUtils.isNotBlank(body)) &#123;</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"> &#125;</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>) &#123;</span><br><span class="line"> customReqConf.setConnectTimeout(connTimeout);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">if</span> (readTimeout != <span class="literal">null</span>) &#123;</span><br><span class="line"> customReqConf.setSocketTimeout(readTimeout);</span><br><span class="line"> &#125;</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">&quot;https&quot;</span>)) &#123;</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"> &#125; <span class="keyword">else</span> &#123;</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"> &#125;</span><br><span class="line"> result = IOUtils.toString(res.getEntity().getContent(), charset);</span><br><span class="line"> &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line"> post.releaseConnection();</span><br><span class="line"> <span class="keyword">if</span> (url.startsWith(<span class="string">&quot;https&quot;</span>) &amp;&amp; client != <span class="literal">null</span>&amp;&amp; client <span class="keyword">instanceof</span> CloseableHttpClient) &#123;</span><br><span class="line"> ((CloseableHttpClient) client).close();</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> result;</span><br><span class="line"> &#125;</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&lt;String, String&gt; params, Map&lt;String, String&gt; headers, Integer connTimeout,Integer readTimeout)</span> <span class="keyword">throws</span> ConnectTimeoutException,</span><br><span class="line"> SocketTimeoutException, Exception &#123;</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> &#123;</span><br><span class="line"> <span class="keyword">if</span> (params != <span class="literal">null</span> &amp;&amp; !params.isEmpty()) &#123;</span><br><span class="line"> List&lt;NameValuePair&gt; formParams = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;NameValuePair&gt;();</span><br><span class="line"> Set&lt;Entry&lt;String, String&gt;&gt; entrySet = params.entrySet();</span><br><span class="line"> <span class="keyword">for</span> (Entry&lt;String, String&gt; entry : entrySet) &#123;</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"> &#125;</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"> &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (headers != <span class="literal">null</span> &amp;&amp; !headers.isEmpty()) &#123;</span><br><span class="line"> <span class="keyword">for</span> (Entry&lt;String, String&gt; entry : headers.entrySet()) &#123;</span><br><span class="line"> post.addHeader(entry.getKey(), entry.getValue());</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</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>) &#123;</span><br><span class="line"> customReqConf.setConnectTimeout(connTimeout);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">if</span> (readTimeout != <span class="literal">null</span>) &#123;</span><br><span class="line"> customReqConf.setSocketTimeout(readTimeout);</span><br><span class="line"> &#125;</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">&quot;https&quot;</span>)) &#123;</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"> &#125; <span class="keyword">else</span> &#123;</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"> &#125;</span><br><span class="line"> <span class="keyword">return</span> IOUtils.toString(res.getEntity().getContent(), <span class="string">&quot;UTF-8&quot;</span>);</span><br><span class="line"> &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line"> post.releaseConnection();</span><br><span class="line"> <span class="keyword">if</span> (url.startsWith(<span class="string">&quot;https&quot;</span>) &amp;&amp; client != <span class="literal">null</span></span><br><span class="line"> &amp;&amp; client <span class="keyword">instanceof</span> CloseableHttpClient) &#123;</span><br><span class="line"> ((CloseableHttpClient) client).close();</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</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 &#123;</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">&quot;&quot;</span>;</span><br><span class="line"> <span class="keyword">try</span> &#123;</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>) &#123;</span><br><span class="line"> customReqConf.setConnectTimeout(connTimeout);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">if</span> (readTimeout != <span class="literal">null</span>) &#123;</span><br><span class="line"> customReqConf.setSocketTimeout(readTimeout);</span><br><span class="line"> &#125;</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">&quot;https&quot;</span>)) &#123;</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"> &#125; <span class="keyword">else</span> &#123;</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"> &#125;</span><br><span class="line"></span><br><span class="line"> result = IOUtils.toString(res.getEntity().getContent(), charset);</span><br><span class="line"> &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line"> get.releaseConnection();</span><br><span class="line"> <span class="keyword">if</span> (url.startsWith(<span class="string">&quot;https&quot;</span>) &amp;&amp; client != <span class="literal">null</span> &amp;&amp; client <span class="keyword">instanceof</span> CloseableHttpClient) &#123;</span><br><span class="line"> ((CloseableHttpClient) client).close();</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> result;</span><br><span class="line"> &#125;</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(&quot;unused&quot;)</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> &#123;</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> &amp;&amp; ressponse.getEntity().getContentType() != <span class="literal">null</span> &amp;&amp; ressponse.getEntity().getContentType().getValue() != <span class="literal">null</span>) &#123;</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">&quot;charset=&quot;</span>)) &#123;</span><br><span class="line"> <span class="keyword">return</span> contentType.substring(contentType.indexOf(<span class="string">&quot;charset=&quot;</span>) + <span class="number">8</span>);</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">null</span>;</span><br><span class="line"> &#125;</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 &#123;</span><br><span class="line"> <span class="keyword">try</span> &#123;</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>() &#123;</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 &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;).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>() &#123;</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> &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"> &#125;</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 &#123;</span><br><span class="line"> &#125;</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 &#123;</span><br><span class="line"> &#125;</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 &#123;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;);</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"> &#125; <span class="keyword">catch</span> (GeneralSecurityException e) &#123;</span><br><span class="line"> <span class="keyword">throw</span> e;</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</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(&quot;/api/ucenter/wx&quot;)</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> &#123;</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(&quot;/getLoginParam&quot;)</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> &#123;</span><br><span class="line"> <span class="keyword">try</span> &#123;</span><br><span class="line"> HashMap&lt;String, Object&gt; map = <span class="keyword">new</span> <span class="title class_">HashMap</span>&lt;&gt;();</span><br><span class="line"> map.put(<span class="string">&quot;appid&quot;</span>, ConstantPropertiesUtil.WX_OPEN_APP_ID);</span><br><span class="line"> map.put(<span class="string">&quot;scope&quot;</span>, <span class="string">&quot;snsapi_login&quot;</span>);</span><br><span class="line"> map.put(<span class="string">&quot;redirect_uri&quot;</span>, URLEncoder.encode(ConstantPropertiesUtil.WX_OPEN_REDIRECT_URL, <span class="string">&quot;utf-8&quot;</span>));</span><br><span class="line"> map.put(<span class="string">&quot;state&quot;</span>, System.currentTimeMillis() + <span class="string">&quot;&quot;</span>);<span class="comment">//原样返回,可以没有</span></span><br><span class="line"> <span class="keyword">return</span> Result.ok(map);</span><br><span class="line"> &#125; <span class="keyword">catch</span> (UnsupportedEncodingException e) &#123;</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> <span class="keyword">return</span> Result.fail();</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</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(&quot;/callback&quot;)</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>&#123;</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">&quot;https://api.weixin.qq.com/sns/oauth2/access_token&quot;</span>) <span class="comment">//请求的固定地址</span></span><br><span class="line"> .append(<span class="string">&quot;?appid=%s&quot;</span>) <span class="comment">//%s占位符</span></span><br><span class="line"> .append(<span class="string">&quot;&amp;secret=%s&quot;</span>)</span><br><span class="line"> .append(<span class="string">&quot;&amp;code=%s&quot;</span>)</span><br><span class="line"> .append(<span class="string">&quot;&amp;grant_type=authorization_code&quot;</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> &#123;</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">&quot;access_token&quot;</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">&quot;openid&quot;</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">&quot;https://api.weixin.qq.com/sns/userinfo&quot;</span> +</span><br><span class="line"> <span class="string">&quot;?access_token=%s&quot;</span> +</span><br><span class="line"> <span class="string">&quot;&amp;openid=%s&quot;</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">&quot;nickname&quot;</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">&quot;sex&quot;</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">&quot;language&quot;</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">&quot;city&quot;</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">&quot;province&quot;</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">&quot;country&quot;</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">&quot;headimgurl&quot;</span>);<span class="comment">//头像的url地址</span></span><br><span class="line"> System.out.println(<span class="string">&quot;昵称:&quot;</span>+nickname+<span class="string">&quot;,性别:&quot;</span>+sex+<span class="string">&quot;,语言:&quot;</span>+language+<span class="string">&quot;,城市:&quot;</span>+city+<span class="string">&quot;,省份:&quot;</span>+province+<span class="string">&quot;,注册国家:&quot;</span>+country+<span class="string">&quot;,头像地址:&quot;</span>+headimgurl);</span><br><span class="line"> <span class="comment">//TODO 将扫码人的信息添加到数据库中</span></span><br><span class="line"> &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line"> e.printStackTrace();</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> <span class="string">&quot;redirect:地址信息&amp;参数信息(用户信息或者token信息等)&quot;</span>;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</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&amp;fromSubId=1&amp;subcmd=all&amp;uin=2602183349&amp;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>