- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章详解用JWT对SpringCloud进行认证和鉴权由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
jwt(json web token)是基于rfc 7519标准定义的一种可以安全传输的小巧和自包含的json对象。由于数据是使用数字签名的,所以是可信任的和安全的。jwt可以使用hmac算法对secret进行加密或者使用rsa的公钥私钥对来进行签名.
jwt通常由头部(header),负载(payload),签名(signature)三个部分组成,中间以.号分隔,其格式为header.payload.signature 。
header:声明令牌的类型和使用的算法 。
payload:也称为jwt claims,包含用户的一些信息 。
系统保留的声明(reserved claims):
公共的声明(public):见 http://www.iana.org/assignments/jwt/jwt.xhtml 。
私有的声明(private claims):根据业务需要自己定义的数据 。
signature:签名 。
签名格式: hmacsha256(base64urlencode(header) + "." + base64urlencode(payload), secret) 。
jwt的特点:
认证原理:
jwt的使用方式:一种做法是放在http请求的头信息authorization字段里面,格式如下:
authorization: <token> 。
需要将服务器设置为接受来自所有域的请求,用access-control-allow-origin: * 。
另一种做法是,跨域的时候,jwt就放在post请求的数据体里面.
对jwt实现token续签的做法:
1、额外生成一个refreshtoken用于获取新token,refreshtoken需存储于服务端,其过期时间比jwt的过期时间要稍长.
2、用户携带refreshtoken参数请求token刷新接口,服务端在判断refreshtoken未过期后,取出关联的用户信息和当前token.
3、使用当前用户信息重新生成token,并将旧的token置于黑名单中,返回新的token.
创建用于登录认证的工程auth-service:
1、 创建pom.xml文件 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
<project xmlns=
"http://maven.apache.org/pom/4.0.0"
xmlns:xsi=
"http://www.w3.org/2001/xmlschema-instance"
xsi:schemalocation=
"http://maven.apache.org/pom/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
>
<modelversion>
4.0
.
0
</modelversion>
<groupid>com.seasy.springcloud</groupid>
<artifactid>auth-service</artifactid>
<version>
1.0
.
0
</version>
<packaging>jar</packaging>
<parent>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-parent</artifactid>
<version>
2.0
.
8
.release</version>
<relativepath/>
</parent>
<properties>
<java.version>
1.8
</java.version>
<project.build.sourceencoding>utf-
8
</project.build.sourceencoding>
<project.reporting.outputencoding>utf-
8
</project.reporting.outputencoding>
</properties>
<dependencies>
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-web</artifactid>
</dependency>
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-actuator</artifactid>
</dependency>
<!-- spring cloud -->
<dependency>
<groupid>org.springframework.cloud</groupid>
<artifactid>spring-cloud-starter-netflix-eureka-client</artifactid>
</dependency>
<!-- redis -->
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-data-redis</artifactid>
</dependency>
<dependency>
<groupid>org.apache.commons</groupid>
<artifactid>commons-pool2</artifactid>
</dependency>
<!-- jwt -->
<dependency>
<groupid>com.auth0</groupid>
<artifactid>java-jwt</artifactid>
<version>
3.7
.
0
</version>
</dependency>
</dependencies>
<dependencymanagement>
<dependencies>
<dependency>
<groupid>org.springframework.cloud</groupid>
<artifactid>spring-cloud-dependencies</artifactid>
<version>finchley.release</version>
<type>pom</type>
<scope>
import
</scope>
</dependency>
</dependencies>
</dependencymanagement>
</project>
|
2、jwt工具类 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
public
class
jwtutil {
public
static
final
string secret_key =
"123456"
;
//秘钥
public
static
final
long
token_expire_time =
5
*
60
*
1000
;
//token过期时间
public
static
final
long
refresh_token_expire_time =
10
*
60
*
1000
;
//refreshtoken过期时间
private
static
final
string issuer =
"issuer"
;
//签发人
/**
* 生成签名
*/
public
static
string generatetoken(string username){
date now =
new
date();
algorithm algorithm = algorithm.hmac256(secret_key);
//算法
string token = jwt.create()
.withissuer(issuer)
//签发人
.withissuedat(now)
//签发时间
.withexpiresat(
new
date(now.gettime() + token_expire_time))
//过期时间
.withclaim(
"username"
, username)
//保存身份标识
.sign(algorithm);
return
token;
}
/**
* 验证token
*/
public
static
boolean
verify(string token){
try
{
algorithm algorithm = algorithm.hmac256(secret_key);
//算法
jwtverifier verifier = jwt.require(algorithm)
.withissuer(issuer)
.build();
verifier.verify(token);
return
true
;
}
catch
(exception ex){
ex.printstacktrace();
}
return
false
;
}
/**
* 从token获取username
*/
public
static
string getusername(string token){
try
{
return
jwt.decode(token).getclaim(
"username"
).asstring();
}
catch
(exception ex){
ex.printstacktrace();
}
return
""
;
}
}
|
3、logincontroller类 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
@restcontroller
public
class
logincontroller {
@autowired
stringredistemplate redistemplate;
/**
* 登录认证
* @param username 用户名
* @param password 密码
*/
@getmapping
(
"/login"
)
public
authresult login(
@requestparam
string username,
@requestparam
string password) {
if
(
"admin"
.equals(username) &&
"admin"
.equals(password)){
//生成token
string token = jwtutil.generatetoken(username);
//生成refreshtoken
string refreshtoken = stringutil.getuuidstring();
//数据放入redis
redistemplate.opsforhash().put(refreshtoken,
"token"
, token);
redistemplate.opsforhash().put(refreshtoken,
"username"
, username);
//设置token的过期时间
redistemplate.expire(refreshtoken, jwtutil.refresh_token_expire_time, timeunit.milliseconds);
return
new
authresult(
0
,
"success"
, token, refreshtoken);
}
else
{
return
new
authresult(
1001
,
"username or password error"
);
}
}
/**
* 刷新token
*/
@getmapping
(
"/refreshtoken"
)
public
authresult refreshtoken(
@requestparam
string refreshtoken) {
string username = (string)redistemplate.opsforhash().get(refreshtoken,
"username"
);
if
(stringutil.isempty(username)){
return
new
authresult(
1003
,
"refreshtoken error"
);
}
//生成新的token
string newtoken = jwtutil.generatetoken(username);
redistemplate.opsforhash().put(refreshtoken,
"token"
, newtoken);
return
new
authresult(
0
,
"success"
, newtoken, refreshtoken);
}
@getmapping
(
"/"
)
public
string index() {
return
"auth-service: "
+ localdatetime.now().format(datetimeformatter.ofpattern(
"yyyy-mm-dd hh:mm:ss"
));
}
}
|
4、application配置信息 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
spring.application.name=auth-service
server.port=
4040
eureka.instance.hostname=${spring.cloud.client.ip-address}
eureka.instance.instance-id=${spring.cloud.client.ip-address}:${server.port}
eureka.instance.prefer-ip-address=
true
eureka.client.service-url.defaultzone=http:
//root:123456@${eureka.instance.hostname}:7001/eureka/
#redis
spring.redis.database=
0
spring.redis.timeout=3000ms
spring.redis.lettuce.pool.max-active=
100
spring.redis.lettuce.pool.max-wait=-1ms
spring.redis.lettuce.pool.min-idle=
0
spring.redis.lettuce.pool.max-idle=
8
#standalone
spring.redis.host=
192.168
.
134.134
spring.redis.port=
7001
#sentinel
#spring.redis.sentinel.master=mymaster
#spring.redis.sentinel.nodes=
192.168
.
134.134
:
26379
,
192.168
.
134.134
:
26380
|
5、启动类 。
1
2
3
4
5
6
7
|
@springbootapplication
@enableeurekaclient
public
class
main{
public
static
void
main(string[] args){
springapplication.run(main.
class
, args);
}
}
|
改造springcloud gateway工程 。
1、在pom.xml文件添加依赖 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<!-- redis -->
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-data-redis</artifactid>
</dependency>
<dependency>
<groupid>org.apache.commons</groupid>
<artifactid>commons-pool2</artifactid>
</dependency>
<!-- jwt -->
<dependency>
<groupid>com.auth0</groupid>
<artifactid>java-jwt</artifactid>
<version>
3.7
.
0
</version>
</dependency>
|
2、创建全局过滤器jwtauthfilter 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
@component
public
class
jwtauthfilter
implements
globalfilter, ordered{
@override
public
int
getorder() {
return
-
100
;
}
@override
public
mono<
void
> filter(serverwebexchange exchange, gatewayfilterchain chain) {
string url = exchange.getrequest().geturi().getpath();
//忽略以下url请求
if
(url.indexof(
"/auth-service/"
) >=
0
){
return
chain.filter(exchange);
}
//从请求头中取得token
string token = exchange.getrequest().getheaders().getfirst(
"authorization"
);
if
(stringutil.isempty(token)){
serverhttpresponse response = exchange.getresponse();
response.setstatuscode(httpstatus.ok);
response.getheaders().add(
"content-type"
,
"application/json;charset=utf-8"
);
response res =
new
response(
401
,
"401 unauthorized"
);
byte
[] responsebyte = jsonobject.fromobject(res).tostring().getbytes(standardcharsets.utf_8);
databuffer buffer = response.bufferfactory().wrap(responsebyte);
return
response.writewith(flux.just(buffer));
}
//请求中的token是否在redis中存在
boolean
verifyresult = jwtutil.verify(token);
if
(!verifyresult){
serverhttpresponse response = exchange.getresponse();
response.setstatuscode(httpstatus.ok);
response.getheaders().add(
"content-type"
,
"application/json;charset=utf-8"
);
response res =
new
response(
1004
,
"invalid token"
);
byte
[] responsebyte = jsonobject.fromobject(res).tostring().getbytes(standardcharsets.utf_8);
databuffer buffer = response.bufferfactory().wrap(responsebyte);
return
response.writewith(flux.just(buffer));
}
return
chain.filter(exchange);
}
}
|
3、关键的application配置信息 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
spring:
application:
name: service-gateway
cloud:
gateway:
discovery:
locator:
enabled:
true
lowercaseserviceid:
true
routes:
#认证服务路由
- id: auth-service
predicates:
- path=/auth-service/**
uri: lb:
//auth-service
filters:
- stripprefix=
1
|
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我.
原文链接:https://www.jianshu.com/p/cf9ad8c3621d 。
最后此篇关于详解用JWT对SpringCloud进行认证和鉴权的文章就讲到这里了,如果你想了解更多关于详解用JWT对SpringCloud进行认证和鉴权的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我喜欢 smartcase,也喜欢 * 和 # 搜索命令。但我更希望 * 和 # 搜索命令区分大小写,而/和 ?搜索命令遵循 smartcase 启发式。 是否有隐藏在某个地方我还没有找到的设置?我宁
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题? Update the question所以它是on-topic对于堆栈溢出。 10年前关闭。 Improve this qu
从以下网站,我找到了执行java AD身份验证的代码。 http://java2db.com/jndi-ldap-programming/solution-to-sslhandshakeexcepti
似乎 melt 会使用 id 列和堆叠的测量变量 reshape 您的数据框,然后通过转换让您执行聚合。 ddply,从 plyr 包看起来非常相似..你给它一个数据框,几个用于分组的列变量和一个聚合
我的问题是关于 memcached。 Facebook 使用 memcached 作为其结构化数据的缓存,以减少用户的延迟。他们在 Linux 上使用 UDP 优化了 memcached 的性能。 h
在 Camel route ,我正在使用 exec 组件通过 grep 进行 curl ,但使用 ${HOSTNAME} 的 grep 无法正常工作,下面是我的 Camel 路线。请在这方面寻求帮助。
我正在尝试执行相当复杂的查询,在其中我可以排除与特定条件集匹配的项目。这是一个 super 简化的模型来解释我的困境: class Thing(models.Model) user = mod
我正在尝试执行相当复杂的查询,我可以在其中排除符合特定条件集的项目。这里有一个 super 简化的模型来解释我的困境: class Thing(models.Model) user = mod
我发现了很多嵌入/内容项目的旧方法,并且我遵循了在这里找到的最新方法(我假设):https://blog.angular-university.io/angular-ng-content/ 我正在尝试
我正在寻找如何使用 fastify-nextjs 启动 fastify-cli 的建议 我曾尝试将代码简单地添加到建议的位置,但它不起作用。 'use strict' const path = req
我正在尝试将振幅 js 与 React 和 Gatsby 集成。做 gatsby developer 时一切看起来都不错,因为它发生在浏览器中,但是当我尝试 gatsby build 时,我收到以下错
我试图避免过度执行空值检查,但同时我想在需要使代码健壮的时候进行空值检查。但有时我觉得它开始变得如此防御,因为我没有实现 API。然后我避免了一些空检查,但是当我开始单元测试时,它开始总是等待运行时异
尝试进行包含一些 NOT 的 Kibana 搜索,但获得包含 NOT 的结果,因此猜测我的语法不正确: "chocolate" AND "milk" AND NOT "cow" AND NOT "tr
我正在使用开源代码共享包在 iOS 中进行 facebook 集成,但收到错误“FT_Load_Glyph failed: glyph 65535: error 6”。我在另一台 mac 机器上尝试了
我正在尝试估计一个标准的 tobit 模型,该模型被审查为零。 变量是 因变量 : 幸福 自变量 : 城市(芝加哥,纽约), 性别(男,女), 就业(0=失业,1=就业), 工作类型(失业,蓝色,白色
我有一个像这样的项目布局 样本/ 一种/ 源/ 主要的/ java / java 资源/ .jpg 乙/ 源/ 主要的/ java / B.java 资源/ B.jpg 构建.gradle 设置.gr
如何循环遍历数组中的多个属性以及如何使用map函数将数组中的多个属性显示到网页 import React, { Component } from 'react'; import './App.css'
我有一个 JavaScript 函数,它进行 AJAX 调用以返回一些数据,该调用是在选择列表更改事件上触发的。 我尝试了多种方法来在等待时显示加载程序,因为它当前暂停了选择列表,从客户的 Angul
可能以前问过,但找不到。 我正在用以下形式写很多语句: if (bar.getFoo() != null) { this.foo = bar.getFoo(); } 我想到了三元运算符,但我认
我有一个表单,在将其发送到 PHP 之前我正在执行一些验证 JavaScript,验证后的 JavaScript 函数会发布用户在 中输入的文本。页面底部的标签;然而,此消息显示短暂,然后消失...
我是一名优秀的程序员,十分优秀!