OAuth2.0-2jwt令牌
JWT令牌
解决了之前普通令牌每次都要远程校验令牌带来得网络消耗;(有网友说可以将令牌验证从认证服务器上放到各个资源服务器上,不知是否可行?)
JWT令牌的优点:
1、jwt基于json,非常方便解析。
2、可以在令牌中自定义丰富的内容,易扩展。
3、通过非对称加密算法及数字签名技术,JWT防止篡改,安全性高。
4、资源服务使用JWT可不依赖认证服务即可完成授权。
缺点:
1、JWT令牌较长,占存储空间比较大。
1.1 令牌结构
通过学习JWT令牌结构为自定义jwt令牌打好基础。
JWT令牌由三部分组成,每部分中间使用点(.)分隔,比如:xxxxx.yyyyy.zzzzz
Header
头部包括令牌的类型(即JWT)及使用的哈希算法(如HMAC SHA256或RSA) 一个例子如下:
下边是Header部分的内容:
{
"alg": "HS256",
"typ": "JWT"
}
将上边的内容使用Base64Url编码,得到一个字符串就是JWT令牌的第一部分。
Payload
第二部分是负载,内容也是一个json对象,它是存放有效信息的地方,它可以存放jwt提供的现成字段,比如:iss(签发者),exp(过期时间戳), sub(面向的用户)等,也可自定义字段。
此部分不建议存放敏感信息,因为此部分可以解码还原原始内容。
最后将第二部分负载使用Base64Url编码,得到一个字符串就是JWT令牌的第二部分。
{
"sub": "1234567890",
"name": "456",
"admin": true
}
Signature
第三部分是签名,此部分用于防止jwt内容被篡改。
这个部分使用base64url将前两部分进行编码,编码后使用点(.)连接组成字符串,最后使用header中声明签名算法进行签名。
一个例子:
HMACSHA256(
base64UrlEncode(header) + "." +base64UrlEncode(payload),secret
)
base64UrlEncode(header):jwt令牌的第一部分。
base64UrlEncode(payload):jwt令牌的第二部分。
secret:签名所使用的密钥。
有网友说:实际投产中,使用redis好一点,如果客户端过多,jwt就会很臃肿?
1.授权服务AuthorizationServerConfig
@Configuration
//开启oauth2,auth server模式
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { @Autowired
private PasswordEncoder passwordEncoder; //配置客户端
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
//client的id和密码
.withClient("client1")
.secret(passwordEncoder.encode("123123"))
//给client一个id,这个在client的配置里要用的
.resourceIds("resource1")
//允许的申请token的方式,测试用例在test项目里都有.
//authorization_code授权码模式,这个是标准模式
//implicit简单模式,这个主要是给无后台的纯前端项目用的
//password密码模式,直接拿用户的账号密码授权,不安全
//client_credentials客户端模式,用clientid和密码授权,和用户无关的授权方式
//refresh_token使用有效的refresh_token去重新生成一个token,之前的会失效
.authorizedGrantTypes("authorization_code", "password", "client_credentials", "implicit", "refresh_token")
//授权的范围,每个resource会设置自己的范围.
.scopes("scope1", "scope2")
//这个是设置要不要弹出确认授权页面的.
.autoApprove(false)
//这个相当于是client的域名,重定向给code的时候会跳转这个域名
.redirectUris("http://www.baidu.com");
}
@Autowired
private ClientDetailsService clientDetailsService;
@Autowired
private TokenStore tokenStore;
@Autowired
private JwtAccessTokenConverter tokenConverter;
//配置token管理服务
@Bean
public AuthorizationServerTokenServices tokenServices() {
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setClientDetailsService(clientDetailsService);
defaultTokenServices.setSupportRefreshToken(true);
//配置token的存储方法
defaultTokenServices.setTokenStore(tokenStore);
defaultTokenServices.setAccessTokenValiditySeconds(300);
defaultTokenServices.setRefreshTokenValiditySeconds(1500);
//配置token增强,把一般token转换为jwt token
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenConverter));
defaultTokenServices.setTokenEnhancer(tokenEnhancerChain);
return defaultTokenServices;
}
//密码模式才需要配置,认证管理器
@Autowired
private AuthenticationManager authenticationManager; //把上面的各个组件组合在一起
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager)//认证管理器
.authorizationCodeServices(new InMemoryAuthorizationCodeServices())//授权码管理
.tokenServices(tokenServices())//token管理
.allowedTokenEndpointRequestMethods(HttpMethod.POST);
}
//配置哪些接口可以被访问
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.tokenKeyAccess("permitAll()")///oauth/token_key公开
.checkTokenAccess("permitAll()")///oauth/check_token公开
.allowFormAuthenticationForClients();//允许表单认证
}
}
TokenConfig
@Configuration
public class TokenConfig { //配置如何把普通token转换成jwt token
@Bean
public JwtAccessTokenConverter tokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); //使用对称秘钥加密token,resource那边会用这个秘钥校验token
converter.setSigningKey("uaa123");
return converter;
} //配置token的存储方法
@Bean
public TokenStore tokenStore() {
//把用户信息都存储在token当中,相当于存储在客户端,性能好很多
return new JwtTokenStore(tokenConverter());
}
}
WebSecurityConfig
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
} //密码模式才需要配置,认证管理器
@Bean
@Override
protected AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
} @Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.anyRequest().permitAll() .and()
.formLogin() .and()
.logout();
} @Override
@Bean
public UserDetailsService userDetailsService() {
/**
* 基于内存创建用户
*/
InMemoryUserDetailsManager manager=new InMemoryUserDetailsManager(); manager.createUser(User.withUsername("zhangsan").password(passwordEncoder().encode("123")).authorities("admin").build());
manager.createUser(User.withUsername("lisi").password(passwordEncoder().encode("123")).authorities("user").build());
return manager;
}
}
2.资源服务ResourceServerConfig
@Configuration
//开启oauth2,reousrce server模式
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Autowired
private TokenStore tokenStore; @Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources
//设置我这个resource的id, 这个在auth中配置, 这里必须照抄
.resourceId("resource1")
.tokenStore(tokenStore)//原来是 .tokenServices(tokenServices())去调用远程验证,现在只需要自己验证自己即可
//这个貌似是配置要不要把token信息记录在session中
.stateless(true);
} @Override
public void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests() //本项目所需要的授权范围,这个scope是写在auth服务的配置里的
.antMatchers("/**").access("#oauth2.hasScope('scope1')") .and() //这个貌似是配置要不要把token信息记录在session中
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}
TokenConfig
@Configuration
public class TokenConfig { //配置如何把普通token转换成jwt token
@Bean
public JwtAccessTokenConverter tokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); //使用对称秘钥加密token,resource那边会用这个秘钥校验token
converter.setSigningKey("uaa123");//密钥必须跟授权服务那边一样!
return converter;
} //配置token的存储方法
@Bean
public TokenStore tokenStore() {
//把用户信息都存储在token当中,相当于存储在客户端,性能好很多
return new JwtTokenStore(tokenConverter());
}
}
WebSecurityConfig
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.anyRequest().permitAll();
}
}
验证方式:参考上一章
//授权码模式
//浏览器访问
http://127.0.0.1:9011/oauth/authorize?client_id=client1&response_type=code&scope=scope1&redirect_uri=http://www.baidu.com
带令牌访问资源:
无需远程验证,直接令牌自己根据对称加解密 即可获取用户令牌内得权限信息
OAuth2.0-2jwt令牌的更多相关文章
- Spring Security 实战干货: 简单的认识 OAuth2.0 协议
1.前言 欢迎阅读 Spring Security 实战干货 系列文章 .OAuth2.0 是近几年比较流行的授权机制,对于普通用户来说可能每天你都在用它,我们经常使用的第三方登录大都基于 OAuth ...
- Spring Security OAuth2.0认证授权四:分布式系统认证授权
Spring Security OAuth2.0认证授权系列文章 Spring Security OAuth2.0认证授权一:框架搭建和认证测试 Spring Security OAuth2.0认证授 ...
- OAuth2.0学习(1-8) 授权方式五之Access_Token令牌过期更新
OAuth2.0的Access_Token令牌过期更新 如果用户访问的时候,客户端的"访问令牌"已经过期,则需要使用"更新令牌"申请一个新的访问令牌. 客户端发 ...
- Spring Security OAuth2.0认证授权三:使用JWT令牌
Spring Security OAuth2.0系列文章: Spring Security OAuth2.0认证授权一:框架搭建和认证测试 Spring Security OAuth2.0认证授权二: ...
- OAuth2.0实战!使用JWT令牌认证!
大家好,我是不才陈某~ 这是<Spring Security 进阶>的第3篇文章,往期文章如下: 实战!Spring Boot Security+JWT前后端分离架构登录认证! 妹子始终没 ...
- OAuth2.0 微博登陆网站功能的实现(一)获取用户授权及令牌 Access Token
在登陆一些网站的时候,可以选择登陆方式为第三方登陆,例如微博登陆,以爱奇艺为例,进入首页,点击 ”登陆“,会弹出登录框: 除了本站登陆外,还可以选择其他第三方登陆,比如微博登陆.QQ 登陆.微信登陆等 ...
- SimpleSSO:使用Microsoft.Owin.Security.OAuth搭建OAuth2.0授权服务端
目录 前言 OAuth2.0简介 授权模式 (SimpleSSO示例) 使用Microsoft.Owin.Security.SimpleSSO模拟OpenID认证 通过authorization co ...
- 深入理解OAuth2.0协议
1. 引言 如果你开车去酒店赴宴,你经常会苦于找不到停车位而耽误很多时间.是否有好办法可以避免这个问题呢?有的,听说有一些豪车的车主就不担心这个问题.豪车一般配备两种钥匙:主钥匙和泊车钥匙.当你到酒店 ...
- 微信开放平台开发——网页微信扫码登录(OAuth2.0)
1.OAuth2.0 OAuth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用. 允许用户提供 ...
- 微信公众平台开发——微信授权登录(OAuth2.0)
1.OAuth2.0简介 OAuth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用. 允许用户 ...
随机推荐
- java 面向对象(六):类结构 方法(三) java的值传递机制
java的值传递机制 1.针对于方法内变量的赋值举例: System.out.println("***********基本数据类型:****************"); int ...
- javascript基础(二): 操作BOM对象(重点)
浏览器介绍 javascript和浏览器关系?BOM:浏览器对象模型 IE6~11 Chrome Safari FireFox Opera 三方 QQ浏览器 360浏览器 window window代 ...
- hihoCoder 1049 后序遍历 最详细的解题报告
题目来源:后序遍历 解题思路:开始时我只知道先通过先序.中序求出二叉树,然后再后序遍历二叉树,这当然也是一种解题思路,但是会做一些无用功,比如:计算二叉树.其实,可以直接通过先序序列和中序序列直接求出 ...
- redis入门指南(四)—— redis如何节省空间
写在前面 学习<redis入门指南>笔记,结合实践,只记录重要,明确,属于新知的相关内容. 节省空间 1.redis对于它所支持的五种数据类型,每种都提供了两种及以上的编码方式去存储(具体 ...
- 《Head First 设计模式》:装饰者模式
正文 一.定义 装饰者模式动态地将责任(功能)附加到对象上.若要扩展功能,装饰者提供了比继承更有弹性的替代方案. 要点: 装饰者和被装饰者有相同的超类型. 可以用一个或多个装饰者包装一个对象. 既然装 ...
- servlet的HttpSession与HibernateSession的区别
一.javax.servlet.http.HttpSession是一个抽象接口 它的产生:J2EE的Web程序在运行的时候,会给每一个新的访问者建立一个HttpSession,这个Session是用户 ...
- GPO - General GPO Settings(3)
WMI filtering Setting - Differentiating Installation Between Operations and Architecture. WMI SQL Ge ...
- Ethical Hacking - GAINING ACCESS(16)
CLIENT SIDE ATTACKS - Social Engineering Social Engineering Information gathering Tool: Maltego Gath ...
- Python Ethical Hacking - Malware Analysis(1)
WRITING MALWARE Download file. Execute Code. Send Report. Download & Execute. Execute & Repo ...
- Qt-数据库操作SQLite
1 简介 参考视频:https://www.bilibili.com/video/BV1XW411x7NU?p=88 说明:本文对在Qt中操作SQLite做简要说明. SQLite:SQLite 是 ...