11、访问令牌
11.1、单点登录
11.1.1、用户身份认证
11.1.1.1、单一服务器模式

一般过程如下:
- 用户向服务器发送用户名和密码。
- 验证服务器后,相关数据(如用户名,用户角色等)将保存在当前会话(session)中。
- 服务器向用户返回session_id,session信息都会写入到用户的Cookie。
- 用户的每个后续请求都将通过在Cookie中取出session_id传给服务器。
- 服务器收到session_id并对比之前保存的数据,确认用户的身份。
缺点:
- 单点性能压力,无法扩展。
- 分布式架构中,需要session共享方案,session共享方案存在性能瓶颈。
session共享方案:
session广播:性能瓶颈,不推荐
redis代替session:推荐,性能高
11.1.1.2、SSO(Single Sign On)模式
CAS单点登录、OAuth2

分布式,SSO(single sign on)模式:单点登录英文全称Single Sign On,简称就是SSO。它的解释是:在多个应用系统中,只需要登录一次,就可以访问其他相互信任的应用系统。
- 如图所示,图中有3个系统,分别是业务A、业务B、和SSO。
- 业务A、业务B没有登录模块。
- 而SSO只有登录模块,没有其他的业务模块。
一般过程如下:
- 当业务A、业务B需要登录时,将跳到SSO系统。
- SSO从用户信息数据库中获取用户信息并校验用户信息,SSO系统完成登录。
- 然后将用户信息存入缓存(例如redis)。
- 当用户访问业务A或业务B,需要判断用户是否登录时,将跳转到SSO系统中进行用户身份验证,SSO判断缓存中是否存在用户身份信息。
- 这样,只要其中一个系统完成登录,其他的应用系统也就随之登录了。这就是单点登录(SSO)的定义。
优点 :
用户身份信息独立管理,更好的分布式管理。可以自己扩展安全策略
缺点:
认证服务器访问压力较大。
11.1.1.3、Token模式

优点:
- 无状态: token是无状态,session是有状态的
- 基于标准化:你的API可以采用标准化的 JSON Web Token (JWT)
缺点:
- 占用带宽
- 无法在服务器端销毁
11.2、JWT令牌
11.2.1、访问令牌的类型

11.2.2、JWT令牌
11.2.2.1、什么是JWT令牌
JWT是JSON Web Token的缩写,即JSON Web令牌,是一种自包含令牌。
JWT的使用场景:
- 一种情况是webapi,类似之前的阿里云播放凭证的功能
- 另一种情况是多web服务器下实现无状态分布式身份验证
- JWT官网有一张图描述了JWT的认证过程

JWT的作用:
- JWT 最重要的作用就是对 token信息的防伪作用
JWT的原理:
- 一个JWT由三个部分组成:JWT头、有效载荷、签名哈希最后由这三者组合进行base64编码得到JWT
11.2.2.2、JWT令牌的组成
典型的,一个JWT看起来如下图:
https://jwt.io/

该对象为一个很长的字符串,字符之间通过"."分隔符分为三个子串。
每一个子串表示了一个功能块,总共有以下三个部分:JWT头、有效载荷和签名
JWT头
JWT头部分是一个描述JWT元数据的JSON对象,通常如下所示。
{
"alg": "HS256",
"typ": "JWT"
}
在上面的代码中,alg属性表示签名使用的算法,默认为HMAC SHA256(写为HS256);typ属性表示令牌的类型,JWT令牌统一写为JWT。最后,使用Base64 URL算法将上述JSON对象转换为字符串保存。
有效载荷
有效载荷部分,是JWT的主体内容部分,也是一个JSON对象,包含需要传递的数据。 JWT指定七个默认字段供选择。
sub: 主题
iss: jwt签发者
aud: 接收jwt的一方
iat: jwt的签发时间
exp: jwt的过期时间,这个过期时间必须要大于签发时间
nbf: 定义在什么时间之前,该jwt都是不可用的.
jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。
除以上默认字段外,我们还可以自定义私有字段,如下例:
{
"name": "Helen",
"admin": true,
"avatar": "helen.jpg"
}
请注意,默认情况下JWT是未加密的,任何人都可以解读其内容,因此不要构建隐私信息字段,存放保密信息,以防止信息泄露。
JSON对象也使用Base64 URL算法转换为字符串保存。
签名哈希
签名哈希部分是对上面两部分数据签名,通过指定的算法生成哈希,以确保数据不会被篡改。
首先,需要指定一个密码(secret)。该密码仅仅为保存在服务器中,并且不能向用户公开。然后,使用标头中指定的签名算法(默认情况下为HMAC SHA256)根据以下公式生成签名。
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(claims), secret) ==> 签名hash
在计算出签名哈希后,JWT头,有效载荷和签名哈希的三个部分组合成一个字符串,每个部分用"."分隔,就构成整个JWT对象。
Base64URL算法
如前所述,JWT头和有效载荷序列化的算法都用到了Base64URL。该算法和常见Base64算法类似,稍有差别。
作为令牌的JWT可以放在URL中(例如api.example/?token=xxx)。 Base64中用的三个字符是"+“,”/“和”=“,由于在URL中有特殊含义,因此Base64URL中对他们做了替换:”=“去掉,”+“用”-“替换,”/“用”_"替换,这就是Base64URL算法。
**注意:**base64编码,并不是加密,只是把明文信息变成了不可见的字符串。但是其实只要用一些工具就可以把base64编码解成明文,所以不要在JWT中放入涉及私密的信息。
11.2.2.3、JWT的用法
客户端接收服务器返回的JWT,将其存储在Cookie或localStorage中。
此后,客户端将在与服务器交互中都会带JWT。如果将它存储在Cookie中,就可以自动发送,但是不会跨域,因此一般是将它放入HTTP请求的Header Authorization字段中。
当跨域时,也可以将JWT放置于POST请求的数据主体中。
11.2.3、JWT问题和趋势
1、JWT默认不加密,但可以加密。生成原始令牌后,可以使用该令牌再次对其进行加密。
2、当JWT未加密时,一些私密数据无法通过JWT传输。
3、JWT不仅可用于认证,还可用于信息交换。善用JWT有助于减少服务器请求数据库的次数。
4、JWT的最大缺点是服务器不保存会话状态,所以在使用期间不可能取消令牌或更改令牌的权限。也就是说,一旦JWT签发,在有效期内将会一直有效。
5、JWT本身包含认证信息,因此一旦信息泄露,任何人都可以获得令牌的所有权限。为了减少盗用,JWT的有效期不宜设置太长。对于某些重要操作,用户在使用时应该每次都进行身份验证。
6、为了减少盗用和窃取,JWT不建议使用HTTP协议来传输代码,而是使用加密的HTTPS协议进行传输。
11.3、JWT测试
11.3.1、创建Maven项目
11.3.1.1、项目
项目类型:Maven
groupId:com.atguigu
artifactId:jwt
11.3.1.2、基本依赖
<dependencies>
<!-- JWT -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.7.0</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
11.3.2、测试JWT
11.3.2.1、生成token
package com.atguigu.jwt;
public class JwtTests {
//过期时间,毫秒,24小时
private static long tokenExpiration = 24*60*60*1000;
//秘钥
private static String tokenSignKey = "atguigu123";
@Test
public void testCreateToken(){
String token = Jwts.builder()
.setHeaderParam("typ", "JWT") //令牌类型
.setHeaderParam("alg", "HS256") //签名算法
.setSubject("guli-user") //令牌主题
.setIssuer("atguigu")//签发者
.setAudience("atguigu")//接收者
.setIssuedAt(new Date())//签发时间
.setExpiration(new Date(System.currentTimeMillis() + tokenExpiration)) //过期时间
.setNotBefore(new Date(System.currentTimeMillis() + 20*1000)) //20秒后可用
.setId(UUID.randomUUID().toString())
.claim("nickname", "Helen")
.claim("avatar", "1.jpg")
.signWith(SignatureAlgorithm.HS256, tokenSignKey)//签名哈希
.compact(); //转换成字符串
System.out.println(token);
}
}
11.3.2.2、解析token
@Test
public void testGetUserInfo(){
String token = "jwt字符串";
Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
Claims claims = claimsJws.getBody();
String subject = claims.getSubject();
String issuer = claims.getIssuer();
String audience = claims.getAudience();
Date issuedAt = claims.getIssuedAt();
Date expiration = claims.getExpiration();
Date notBefore = claims.getNotBefore();
String id = claims.getId();
System.out.println(subject);
System.out.println(issuer);
System.out.println(audience);
System.out.println(issuedAt);
System.out.println(expiration);
System.out.println(notBefore);
System.out.println(id);;
String nickname = (String)claims.get("nickname");
String avatar = (String)claims.get("avatar");
System.out.println(nickname);
System.out.println(avatar);
}
12、NuxtJS服务器端渲染
12.1、服务端渲染技术
12.1.1、搜索引擎优化
12.1.1.1、什么是SEO

**总结:**seo是网站为了提高自已的网站排名,获得更多的流量,对网站的结构及内容进行调整和优化,以便搜索引擎 (百度,google等)更好抓取到优质网站的内容。
12.1.1.2、搜索引擎工作流程

常见的SEO方法比如:
- 对url链接的规范化,多用restful风格的url,多用静态资源url;
- 注意keywords、description、title的设置;
- h1-h6、a标签的使用
- 等等
注意:spider对javascript支持不好,ajax获取的JSON数据无法被spider爬取
采用什么技术有利于SEO?要解答这个问题需要理解服务端渲染和客户端渲染。
12.1.2、服务端渲染和客户端渲染
12.1.2.1、什么是服务端渲染
服务端渲染又称SSR (Server Side Render)是在服务端完成页面的内容渲染,而不是在客户端完成页面内容的渲染。
SSR并不是前端特有的技术,我们学习过的JSP技术和Thymeleaf技术就是典型的SSR

服务端渲染的特点:
- 在服务端生成html网页的dom元素
- 客户端(浏览器)只负责显示dom元素内容
12.1.2.2、什么是客户端渲染
客户端(浏览器) 使用AJAX向服务端发起http请 求,获取到了想要的数据,开始渲染html网页,生成dom元素,并最终将网页内容展示给用户。

客户端渲染的特点:
- 在服务端只是给客户端响应的了数据,而不是html网页
- 客户端(浏览器)负责获取服务端的数据生成dom元素
12.1.2.3、两种方式各有什么优缺点?
客户端渲染:
-
缺点:不利于网站进行SEO,因为网站大量使用javascript技术,不利于搜索引擎抓取网页。
-
优点:客户端负责渲染,用户体验性好,服务端只提供数据不用关心用户界面的内容,有利于提高服务端的开发效率。
- 适用场景:对SEO没有要求的系统,比如后台管理类的系统,如电商后台管理,用户管理等。
服务端渲染:
-
优点:有利于SEO,网站通过href的url将搜索引擎直接引到服务端,服务端提供优质的网页内容给搜索引擎。
-
缺点:服务端完成一部分客户端的工作,通常完成一个需求需要修改客户端和服务端的代码,开发效率低,不利于系统的稳定性。
- 适用场景:对SEO有要求的系统,比如:门户首页、商品详情页面等。
12.1.3、Nuxt.js
12.1.3.1、Nuxt.js介绍
移动互联网的兴起促进了web前后端分离开发模式的发展,服务端只专注业务,前端只专注用户体验,比如流行的vue.js实现了功能强大的前端渲染。 但是,对于有SEO需求的网页如果使用前端渲染技术去开发就不利于SEO了,有没有一种即使用vue.js 的前端技术也实现服务端渲染的技术呢?
Nuxt.js 是一个基于 Vue.js 的轻量级应用框架,可以用来创建服务端渲染 (SSR) 应用,也可充当静态站点引擎生成静态站点应用,具有优雅的代码结构分层和热加载等特性。
官网网站:https://zh.nuxtjs.org/
总结:
- 服务器端渲染
- 静态站点引擎
12.1.3.2、Nuxt.js服务器端渲染
下图展示了从客户端请求到Nuxt.js进行服务端渲染的整体的工作流程:

-
用户打开浏览器,输入网址请求到Node.js中的前端View组件
-
部署在Node.js的应用Nuxt.js接收浏览器请求,并请求服务端获取数据
-
Nuxt.js获取到数据后进行服务端渲染
-
Nuxt.js将html网页响应给浏览器
12.2、Nuxt.js入门
12.2.1**、安装和运行**
在线安装方式:参考:https://zh.nuxtjs.org/docs/2.x/get-started/installation
我们可以直接解压资料中的 nuxt-app.zip
12.2.2**、页面、导航和路由**
12.2.2.1、页面
创建pages目录,在pages目录中创建index.vue
<template>
<h1>Hello world!</h1>
</template>
启动项目
npm run dev
访问项目:http://localhost:3000/
再在pages目录中创建一个about.vue页面用于后面的测试
<template>
<h1>关于我们</h1>
</template>
访问页面:http://localhost:3000/about
12.2.2.2、导航
使用标签可以在程序中的不同页面之间导航,相当于标签的作用。一般情况下我们使用连接程序内部的不同的路由地址,使用标签连接站外地址。
pages/index.vue
<template>
<div>
<NuxtLink to="/about">
关于我们
</NuxtLink>
<NuxtLink to="/lend">
我要投资
</NuxtLink>
<NuxtLink to="/user">
用户中心
</NuxtLink>
<a href="http://atguigu.com" target="_blank">尚硅谷</a>
<h1>主页面</h1>
</div>
</template>
12.2.2.3、自动路由
在vue项目中我们需要创建页面,并为每一个页面配置路由,而Nuxt会根据pages路径中的页面自动生成路由配置。
- 基本路由1: /user 指向 pages/user.vue页面
<template>
<div>
<h1>用户中心</h1>
</div>
</template>
- 基本路由2: /lend 指向 pages/lend/index.vue页面
<template>
<div>
<h1>投资产品列表</h1>
<NuxtLink to="/lend/1">
产品1
</NuxtLink>
<NuxtLink to="/lend/2">
产品2
</NuxtLink>
</div>
</template>
- 动态路由:/lend/1、lend/2 等 指向 pages/lend/_id.vue页面,并通过 this.$route.params.id 获取动态路径
<template>
<h1>投资产品 {{ id }}</h1>
</template>
<script>
export default {
data() {
return {
id: null,
}
},
created() {
this.id = this.$route.params.id
},
}
</script>
- 嵌套路由:如果 pages/user.vue 和 pages/user/index.vue 同时存在,我们可以利用嵌套路由
pages/user.vue
<template>
<div>
<h1>用户中心</h1>
<NuxtLink to="/user">
用户信息
</NuxtLink>
<NuxtLink to="/user/account">
用户账户
</NuxtLink>
<!-- user目录下的页面的路由出口 -->
<NuxtChild />
</div>
</template>
pages/user/index.vue
<template>
<h1>用户信息</h1>
</template>
pages/user/account.vue
<template>
<h1>用户账户</h1>
</template>
12.2.3、布局Layout
12.2.3.1、默认布局
如果想拥有统一的页面风格,例如:一致的页头和页尾,可以使用Layout,布局文件的默认的名字是default.vue,放在layouts目录中
注意:新创建的layout重启前端服务器后应用
layouts/default.vue
<template>
<div>
<Nuxt />
<div>default footer</div>
</div>
</template>
12.2.3.2、自定义布局
也可以自定义Layout:layouts/my.vue
<template>
<div>
<Nuxt />
<div>my footer</div>
</div>
</template>
在page中使用layout属性指定布局文件:pages/user.vue
<script>
export default {
layout: 'my',
}
</script>
12.2.3.3、重启服务测试
12.2.4、配置文件
12.2.4.1、Meta Tags and SEO
我们可以在nuxt.config.js中配置如下内容,Nuxt会自动生成网站的标签,这也是搜索引擎优化的一个必要手段。
module.exports = {
head: {
title: '尚融宝',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{
hid: 'meta-key-words',
name: 'keywords',
content:
'尚融宝官网_纽交所上市企业,网络借贷平台,解决个人小额借款,短期借款问题,资金银行存管,安全保障',
},
{
hid: 'description',
name: 'description',
content:
'尚融宝官网_纽交所上市企业,网络借贷平台,解决个人小额借款、短期借款问题。 资金银行存管,安全保障。',
},
],
link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }],
},
}
注意:/favicon.ico 放在 static 目录下
12.2.4.2、样式
step1:创建 assets/css/main.css
body {
background-color: pink;
}
step2:在nuxt.config.js中配置样式(和head同级别)
css: [
// CSS file in the project
'~/assets/css/main.css',
],
12.2.4.3、端口号
在nuxt.config.js中配置
server: {
port: 3001, // default: 3000
},
12.3、远程数据的获取和绑定
12.3.1、整合axios
我们可以引入Nuxt中封装的axios组件,功能更多,编程更简单
参考:https://axios.nuxtjs.org/
12.3.1.1、配置
nuxt.config.js
module.exports = {
modules: [
'@nuxtjs/axios', //引入axios模块
]
}
12.3.1.2、客户端渲染
在pages/index.vue中添加如下代码
<script>
export default {
data() {
return {
ip: null,
}
},
created() {
this.$axios.$get('http://icanhazip.com').then((response) => {
console.log(response)
this.ip = response
})
},
}
</script>
template中显示ip
{{ ip }}
12.3.1.3、服务器端渲染
asyncData({ $axios }) {
console.log('asyncData')
$axios.$get('http://icanhazip.com').then((response) => {
console.log('asyncData', response)
})
return {
ip: response, //这种写法的问题是:前面的远程调用是异步的,无法在这获取到response
}
},
可以将异步调用改为同步调用,可以使用async 和 await关键字使远程调用变为同步,同时让程序更简洁
async asyncData({ $axios }) {
console.log('asyncData')
let response = await $axios.$get('http://icanhazip.com')
return {
message1: response,
}
},
12.3.1.4、axios全局选项
在nuxt.config.js中添加如下配置
axios: {
// Axios options here
baseURL: 'http://icanhazip.com',
},
asyncData中直接写相对路径
let response = await $axios.$get('/')
12.3.1.5、拦截器
创建拦截器插件 plugins/axios.js
export default function({ $axios, redirect }) {
$axios.onRequest((config) => {
console.log('执行请求拦截器 ' + config.url)
})
$axios.onResponse((response) => {
console.log('执行响应拦截器')
return response
})
$axios.onError((error) => {
console.log(error) // for debug
})
}
nuxt.config.js中配置插件
plugins: [
'~/plugins/axios'
]
12.3.1.6、$axios、$get和$axios.get
注意以下$axios访问data的快捷方式问题:
参考地址 https://axios.nuxtjs.org/usage

本文章参考B站 尚硅谷《尚融宝》Java微服务分布式金融项目,仅供个人学习使用,部分内容为本人自己见解,与尚硅谷无关。
JWT令牌与SSO单点登录详解及优缺点
811

被折叠的 条评论
为什么被折叠?



