基于Go语言实现的单点登录系统
2017-12-04 15:30
369 查看
参考:https://jwt.io/introduction/
该单点登录是基于Go语言实现的单点登录系统,下面先简单介绍JWT
紧凑:由于它们尺寸较小,JWT可以通过URL,POST参数或HTTP头内发送。另外,尺寸越小意味着传输速度越快。
自包含:有效载荷包含有关用户的所有必需信息,避免了多次查询数据库的需要。
信息交换:JSON Web Tokens是在各方之间安全传输信息的好方法。因为JWT可以被签名,例如使用公钥/私钥对,所以你可以确定发件人是他们说的那个人。此外,由于使用标头、有效载荷、计算签名,因此您还可以验证内容是否未被篡改。
JWT通常看起来如下所示。
xxxxx.yyyyy.zzzzz
例如:
{
"alg": "HS256",
"typ": "JWT"
}
然后,这个JSON被Base64Url编码,形成JWT的第一部分。
保留的声明(Reserved claims):这是一组预先定义的声明,不是强制性的,但推荐使用,以提供一组有用的,可互操作的声明。 其中一些是:iss(发行人),exp(到期时间),sub(主题),aud(听众)等等。
公开声明(Public claims):这些可以由使用JWT的人员任意定义。 但为避免冲突,应在IANA JSON Web令牌注册表中定义它们,或者将其定义为包含防冲突命名空间的URI。
私有声明(Private claims):这是为了同意使用它们的各方之间共享信息而创建的自定义claims。
有效载荷的一个例子可以是:
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
然后将有效载荷Base64Url进行编码,以形成JSON Web令牌的第二部分。
例如,如果您想使用HMAC SHA256算法,签名将按以下方式创建:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
签名用于验证JWT的发件人是谁,并确保邮件在一路上没有改变。
下面显示了一个JWT,它具有先前的头部和有效载荷编码,并且用秘密签名。
![](http://i2.51cto.com/images/blog/201712/04/a6b66d4f84a0543d7e33cd45fc2a423c.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
无论何时用户想要访问受保护的路由或资源,用户代理都应发送JWT,通常在Authorization头部的Bearer模式中。 头部的内容应该如下所示:
Authorization: Bearer <token>
这是一种无状态身份验证机制,因为用户状态永远不会保存在服务器内存中。 服务器的受保护路由将在授权头中检查有效的JWT,如果存在,则允许用户访问受保护的资源。 由于JWT是独立的,所有必要的信息都在那里,减少了多次查询数据库的需求。
这使您可以完全依赖无状态的数据API,甚至向下游服务发出请求。 无论哪个域正在为您的API提供服务,跨源资源共享(CORS)将不会成为问题,因为它不使用cookie。
下图显示了这个过程:
![](http://i2.51cto.com/images/blog/201712/04/75aed7575140fd938e05e57f3a6f643e.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
由于JSON不如XML冗长,所以在进行编码时,它的大小也会变小,从而使JWT比SAML更紧凑。这使得JWT成为在HTML和HTTP环境中传递的一个很好的选择。
安全方面,SWT只能通过使用HMAC算法的共享秘密进行对称签名。但是,JWT和SAML令牌可以使用X.509证书形式的公钥/私钥对进行签名。与签署JSON的简单性相比,使用XML数字签名签署XML而不引入模糊的安全漏洞是非常困难的。
JSON解析器在大多数编程语言中都很常见,因为它们直接映射到对象。相反,XML没有自然的文档到对象映射。这使得使用JWT比SAML断言更容易。
关于使用情况,JWT在互联网上使用。这突出显示了在多个平台(尤其是移动平台)上JSON Web令牌的客户端处理的简易性。
支持手机号码、用户名、邮箱号码、微信登录
支持手机和邮箱找回密码
支持阿里云通信和互亿无线的短信验证码服务
代码路径:https://github.com/KenmyZhang/single-sign-on
package api
推荐一篇文章
https://www.cnblogs.com/lyzg/p/6132801.html
https://studygolang.com/articles/11793
该单点登录是基于Go语言实现的单点登录系统,下面先简单介绍JWT
JSON Web Token简述
JWT是一个开放的标准(RFC 7519),它定义了一个紧凑且自包含的方式,用于在各方之间以JSON对象安全地传输信息.这些信息可以通过数字签名进行验证和信任。可以使用秘密(使用HMAC算法)或使用RSA的公钥/私钥对来对JWT进行签名。紧凑:由于它们尺寸较小,JWT可以通过URL,POST参数或HTTP头内发送。另外,尺寸越小意味着传输速度越快。
自包含:有效载荷包含有关用户的所有必需信息,避免了多次查询数据库的需要。
JSON Web Token 应用场景
身份验证(Authentication):这是使用JWT最常见的情况。一旦用户登录,每个后续请求将包括JWT,允许用户访问该令牌允许的路由,服务和资源。单点登录是目前广泛使用JWT的一项功能,因为它的开销很小,而且能够轻松地在不同的域中使用。信息交换:JSON Web Tokens是在各方之间安全传输信息的好方法。因为JWT可以被签名,例如使用公钥/私钥对,所以你可以确定发件人是他们说的那个人。此外,由于使用标头、有效载荷、计算签名,因此您还可以验证内容是否未被篡改。
JWT 结构
JSON Web Tokens包含三个由点(.)分隔的部分,它们是:头部、有效载荷、签名JWT通常看起来如下所示。
xxxxx.yyyyy.zzzzz
Header头部
头部通常由两部分组成:令牌的类型(即JWT)和正在使用的散列算法(the hashing algorithm 如HMAC SHA256或RSA)。例如:
{
"alg": "HS256",
"typ": "JWT"
}
然后,这个JSON被Base64Url编码,形成JWT的第一部分。
有效载荷
令牌的第二部分是包含声明的有效载荷。 声明是关于实体(通常是用户)和附加元数据的声明。 有三种类型的声明:保留,公开和私有声明。保留的声明(Reserved claims):这是一组预先定义的声明,不是强制性的,但推荐使用,以提供一组有用的,可互操作的声明。 其中一些是:iss(发行人),exp(到期时间),sub(主题),aud(听众)等等。
请注意,声明名称只有三个字符长,因为JWT是紧凑的。
公开声明(Public claims):这些可以由使用JWT的人员任意定义。 但为避免冲突,应在IANA JSON Web令牌注册表中定义它们,或者将其定义为包含防冲突命名空间的URI。
私有声明(Private claims):这是为了同意使用它们的各方之间共享信息而创建的自定义claims。
有效载荷的一个例子可以是:
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
然后将有效载荷Base64Url进行编码,以形成JSON Web令牌的第二部分。
签名
要创建签名部分,您必须采用编码头部,编码有效载荷,密钥,头部中指定的算法并签名。例如,如果您想使用HMAC SHA256算法,签名将按以下方式创建:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
签名用于验证JWT的发件人是谁,并确保邮件在一路上没有改变。
拼接在一起
输出是三个由点分隔的Base64字符串,可以轻松地在HTML和HTTP环境中传递,而与基于XML的标准(如SAML)相比,它更加紧凑。下面显示了一个JWT,它具有先前的头部和有效载荷编码,并且用秘密签名。
![](http://i2.51cto.com/images/blog/201712/04/a6b66d4f84a0543d7e33cd45fc2a423c.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
JSON Web Token如何工作
在身份验证中(authentication),当用户使用他们的凭证(credentials)成功登录时,将返回一个JSON Web Token,并且必须保存在本地(通常在本地存储中,但也可以使用Cookie),而不是在传统方法中创建会话 服务器并返回一个cookie。无论何时用户想要访问受保护的路由或资源,用户代理都应发送JWT,通常在Authorization头部的Bearer模式中。 头部的内容应该如下所示:
Authorization: Bearer <token>
这是一种无状态身份验证机制,因为用户状态永远不会保存在服务器内存中。 服务器的受保护路由将在授权头中检查有效的JWT,如果存在,则允许用户访问受保护的资源。 由于JWT是独立的,所有必要的信息都在那里,减少了多次查询数据库的需求。
这使您可以完全依赖无状态的数据API,甚至向下游服务发出请求。 无论哪个域正在为您的API提供服务,跨源资源共享(CORS)将不会成为问题,因为它不使用cookie。
下图显示了这个过程:
![](http://i2.51cto.com/images/blog/201712/04/75aed7575140fd938e05e57f3a6f643e.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)
为什么我们应该使用JWT
让我们来谈谈与简单Web令牌(SWT)和安全声明标记语言令牌(SAML)相比,JSON Web令牌(JWT)的好处。由于JSON不如XML冗长,所以在进行编码时,它的大小也会变小,从而使JWT比SAML更紧凑。这使得JWT成为在HTML和HTTP环境中传递的一个很好的选择。
安全方面,SWT只能通过使用HMAC算法的共享秘密进行对称签名。但是,JWT和SAML令牌可以使用X.509证书形式的公钥/私钥对进行签名。与签署JSON的简单性相比,使用XML数字签名签署XML而不引入模糊的安全漏洞是非常困难的。
JSON解析器在大多数编程语言中都很常见,因为它们直接映射到对象。相反,XML没有自然的文档到对象映射。这使得使用JWT比SAML断言更容易。
关于使用情况,JWT在互联网上使用。这突出显示了在多个平台(尤其是移动平台)上JSON Web令牌的客户端处理的简易性。
Go语言实战项目代码
支持手机号码+验证码、邮箱+验证码、微信第三方授权三种方式注册支持手机号码、用户名、邮箱号码、微信登录
支持手机和邮箱找回密码
支持阿里云通信和互亿无线的短信验证码服务
代码路径:https://github.com/KenmyZhang/single-sign-on
package api
import ( "net/http" "regexp" "strconv" "fmt" l4g "github.com/alecthomas/log4go" "github.com/KenmyZhang/single-sign-on/app" "github.com/KenmyZhang/single-sign-on/model" "github.com/KenmyZhang/single-sign-on/utils" "github.com/KenmyZhang/single-sign-on/sqlStore" ) func InitUser() { l4g.Debug(utils.T("api.user.init.debug")) BaseRoutes.User.Handle("", ApiCustomClaimsRequired(getUser)).Methods("GET") BaseRoutes.User.Handle("/image", ApiHandler(getProfileImage)).Methods("GET") BaseRoutes.User.Handle("/image", ApiCustomClaimsRequired(setProfileImage)).Methods("POST") BaseRoutes.Users.Handle("/login", ApiHandler(login)).Methods("POST") BaseRoutes.Users.Handle("/logout", ApiHandler(logout)).Methods("POST") BaseRoutes.Users.Handle("/sendsms", ApiHandler(sendSmsCode)).Methods("POST") BaseRoutes.Users.Handle("/phone/signup", ApiHandler(signupByMobile)).Methods("POST") BaseRoutes.Users.Handle("/phone/login", ApiHandler(loginByMobile)).Methods("POST") BaseRoutes.Users.Handle("/phone/exist", ApiHandler(isMobileExist)).Methods("POST") BaseRoutes.Users.Handle("/phone/reset", ApiHandler(resetPasswordByMobile)).Methods("POST") BaseRoutes.Users.Handle("/email/verify/code/send", ApiHandler(sendVerificationCodeEmail)).Methods("POST") BaseRoutes.Users.Handle("/email/signup", ApiHandler(signupByEmail)).Methods("POST") BaseRoutes.Users.Handle("/email/exist", ApiHandler(isEmailExist)).Methods("POST") BaseRoutes.Users.Handle("/email/reset", ApiHandler(resetPasswordByEmail)).Methods("POST") BaseRoutes.Users.Handle("/search", ApiCustomClaimsRequired(searchUsers)).Methods("POST") } ......
推荐一篇文章
https://www.cnblogs.com/lyzg/p/6132801.html
https://studygolang.com/articles/11793
相关文章推荐
- 基于RFC6265 (HTTP状态管理协议)实现简单的登录系统
- 基于cron、rsync和ssh免密码登录实现Linux系统间自动同步~
- 基于RFC6265 (HTTP状态管理协议)实现简单的登录系统
- 详解基于Sbo DI API独立程序系统登录的实现 推荐
- 基于RFC6265 (HTTP状态管理协议)实现简单的登录系统
- 基于MVC模式实现的登录和分页效果的小系统
- 基于HTTP登录系统的扩展(代码设计实现UI部分)
- 基于RFC6265 (HTTP状态管理协议)实现简单的登录系统
- 基于SSH实现员工管理系统登录权限的过滤器与拦截器的综合使用
- 基于JavaBean,JSP实现登录并显示分页信息的小系统
- 基于Android5.1系统的WebView实现在线登录及全屏播放
- 单点登录系统实现基于SpringBoot
- [转]一种基于智能卡登录Windows系统的实现方式
- 基于通用权限管理系统实现的单点登录
- 一种基于智能卡登录Windows系统的实现方式
- (第一个jdbc入门项目)java实现的登录系统(mysql实现的)
- [分布式java]基于JavaAPI实现消息方式的系统间通信:UDP/IP+BIO
- 基于SSM实现的简易员工管理系统(基于阿里云的网站上线篇)
- 一个基于XML的考试系统的设计与实现
- (系统框架之单点登录)使用 CAS 在 Tomcat 中实现单点登录