赞
踩
在OAuth2.0中“O”是Open的简称,表示“开放”的意思。Auth表示“授权”的意思,所以连起来OAuth表示“开放授权”的意思,它是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用。用一句话总结来说,OAuth2.0是一种授权协议。
OAuth允许用户授权第三方应用访问他存储在另外服务商里的各种信息数据,而这种授权不需要提供用户名和密码提供给第三方应用。
用户登录应用时传统的方式是用户直接进入客户端应用的登录页面输入账号和密码,但有的用户感觉注册后再登录比较繁琐麻烦,于是用户选择使用相关社交账号(微信、QQ、微博)登录,这种方式通过用户的账号和密码去相关社交账号里获取数据存在严重的问题缺陷。 1. 如果第三方应用获取微信中的用户信息,那么你就把你的微信的账号和密码给第三应用。稍微有些安全意识,都不会这样做,这样很不安全;因此使用OAuth2.0可以避免向第三方暴露账号密码;
2. 第三方应用拥有了用户微信的所有权限,用户没法限制第三方应用获得授权的范围和有效期;因此OAuth2.0可以限制授权第三方应用获取微信部分功能,比如只可以获取用户信息,但不可以获取好友列表,有需求时再申请授权访问好友列表的权限;
3. 用户只有修改密码,才能收回赋予第三方应用权限,但是这样做会使得其他所有获得用户授权的第三方应用程序全部失效。
4. 只要有一个第三方应用程序被破解,就会导致用户密码泄漏,以及所有使用微信登录的应用的数据泄漏。
如果某个企业拥有多个应用系统平台,那么每个系统都需要设置一个账号密码,这种操作对于用户来说时繁琐麻烦的,没登录一个系统平台都要输入相应的账号密码,那么可不可以做一个平台,使任意用户可以在这个平台上注册了一个帐号以后,随后这个帐号和密码自动登记到这个平台中作为公共帐号,使用这个账号可以访问其它的已经授权访问的系统。在这种背景下,OAuth2.0协议就诞生了。
OAuth的作用就是让"第三方应用"安全可控地获取"用户"的授权,与"服务商提供商"进行交互。本质是使用token令牌代替用户名密码。
用户每次访问微服务的时候,先去oauth2.0服务登录,登录后再访问微服务网关,微服务网关将请求转发给其他微服务处理。
1. 用户登录成功后,会将令牌信息存入到cookie中(一般建议存入到头文件中)
2. 用户携带Cookie中的令牌访问微服务网关
3. 微服务网关先获取头文件中的令牌信息,如果Header中没有Authorization令牌信息,则取参数中找,参数中如果没有,则取Cookie中找Authorization,最后将令牌信息封装到Header中,并调用其他微服务
4.其他微服务会获取头文件中的Authorization令牌信息,然后匹配令牌数据是否能使用公钥解密,如果解密成功说明用户已登录,解密失败,说明用户未登录
导入依赖
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-oauth2</artifactId>
- </dependency>
修改gateway-server的全局过滤器com.zb.filter.PowerFilter,实现将令牌信息添加到头文件中,代码如下:
package com.zb.filters; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.core.Ordered; import org.springframework.http.HttpStatus; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; @Component public class PowerFilter implements GlobalFilter, Ordered { private static final String AUTHORIZE_TOKEN = "Authorization"; @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest request = exchange.getRequest(); ServerHttpResponse response = exchange.getResponse(); String url = request.getURI().getPath().toString(); System.out.println(url); //不进行身份认证的url if(url.startsWith("/api/area/show")||url.startsWith("/api/user/login")){ return chain.filter(exchange); } String token = request.getHeaders().getFirst(AUTHORIZE_TOKEN); if(StringUtils.isEmpty(token)){ token = request.getQueryParams().getFirst(AUTHORIZE_TOKEN); } if(StringUtils.isEmpty(token)){ response.setStatusCode(HttpStatus.UNAUTHORIZED); return response.setComplete(); //直接响应状态 } //验证token的有效性 try { // Claims claims = JwtUtil.parseJWT(token); //将令牌装到头文件中 request.mutate().header(AUTHORIZE_TOKEN,"Bearer "+token); } catch (Exception e) { e.printStackTrace(); response.setStatusCode(HttpStatus.UNAUTHORIZED); return response.setComplete(); //直接响应状态 } return chain.filter(exchange); } @Override public int getOrder() { return 0; }
}
|
测试:
访问http://localhost:7002/api/user/info/49?Authorization=token,将生成的新令牌放到头文件中,在令牌前面添加Beare
1.上图的业务流程如下:
客户端请求认证服务申请令牌认证服务生成令牌认证服务采用非对称加密算法,使用私钥生成令牌。客户端携带令牌访问资源服务客户端在Http header 中添加: Authorization:Bearer 令牌。资源服务请求认证服务校验令牌的有效性资源服务接收到令牌,使用公钥校验令牌的合法性。令牌有效,资源服务向客户端响应资源信息
在对称加密的时代,加密和解密用的是同一个密钥,这个密钥既用于加密,又用于解密。这样做有一个明显的缺点,如果两个人之间传输文件,两个人都要知道密钥,如果是三个人呢,五个人呢?于是就产生了非对称加密,用一个密钥进行加密(公钥),用另一个密钥进行解密(私钥)。
总结:公钥加密、私钥解密、私钥签名、公钥验签。
Spring Security 提供对JWT的支持,本节我们使用Spring Security 提供的JwtHelper来创建JWT令牌,校验JWT令牌 等操作。 这里JWT令牌我们采用非对称算法进行加密,所以我们要先生成公钥和私钥。
(1)生成密钥证书 下边命令生成密钥证书,采用RSA 算法每个证书包含公钥和私钥
创建一个文件夹,在该文件夹下执行如下命令行:
keytool -genkeypair -alias qianggou -keyalg RSA -keypass qianggou -keystore qianggou.jks -storepass qianggou
Keytool 是一个java提供的证书管理工具
-alias:密钥的别名 -keyalg:使用的hash算法 -keypass:密钥的访问密码 -keystore:密钥库文件名,qianggou.keystore保存了生成的证书 -storepass:密钥库的访问密码
查询证书信息
keytool -list -keystore qianggou.jks
删除别名
keytool -delete -alias qianggou -keystore qianggou.jsk
openssl是一个加解密工具包,这里使用openssl来导出公钥信息。
安装 openssl:http://slproweb.com/products/Win32OpenSSL.html
安装资料目录下的Win64OpenSSL-1_1_0g.exe
配置openssl的path环境变量,如下图:
本教程配置在C:\OpenSSL-Win64\bin
cmd进入qianggou.jks文件所在目录执行如下命令(如下命令在windows下执行,会把-变成中文方式,请将它改成英文的-):
keytool -list -rfc --keystore qianggou.jks | openssl x509 -inform pem -pubkey
下面段内容是公钥
-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhTN8iyCyQEZPUmLw0GB0rH0xeT23w4c8X8thfEtphIBTAKOoUKHxhzBHra/WHLpPw/fV/m9KTvbWCdlBziKWr4P//KtUoa5D3qJupsPDxl9GTXJjG/9y/E+9hHLtl+cM2Qu+RTayFQ4X4ZqLjiOclZZjN8g3MUomu45ab7PVJvuNUGcMq8s+pSvIwHQejYVKlPH8amSqyyxEyzH2MFBXN1c0KoerMfaDV0uzFCsUdOxUlpow9byCPZAspuNbN3DG3xwoHtOErWcchs8TlGMySo2QAeGADmCkH/iIHbF22ytmybIsbK5Ww9T+a1xK+wzzKBAucL+HuK5hLwQlSyuqzQIDAQAB-----END PUBLIC KEY-----
将上边的公钥拷贝到文本public.key文件中,合并为一行,可以将它放到需要实现授权认证的工程中。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。