基于 session 和基于 token 的用户认证方式到底该如何选择?

2016-05-04 11:22:13 +08:00
 qurioust

现在貌似大多数网站用户认证都是基于 session 的,即在服务端生成用户相关的 session 数据,而发给客户端 sesssion_id 存放到 cookie 中,这样用客户端请求时带上 session_id 就可以验证服务器端是否存在 session 数据,以此完成用户认证。这种认证方式,可以更好的在服务端对会话进行控制,安全性比较高(session_id 随机),但是服务端需要存储 session 数据(如内存或数据库),这样无疑增加维护成本和减弱可扩展性(多台服务器)。 CSRF 攻击一般基于 cookie 。另外,如果是原生 app 使用这种服务接口,又因为没有浏览器 cookie 功能,所以接入会相对麻烦。

基于 token 的用户认证是一种服务端无状态的认证方式,服务端不用存放 token 数据。用户验证后,服务端生成一个 token(hash 或 encrypt)发给客户端,客户端可以放到 cookie 或 localStorage 中,每次请求时在 Header 中带上 token ,服务端收到 token 通过验证后即可确认用户身份。这种方式相对 cookie 的认证方式就简单一些,服务端不用存储认证数据,易维护扩展性强, token 存在 localStorage 可避免 CSRF , web 和 app 应用这用接口都比较简单。不过这种方式在加密或解密的时候会有一些性能开销(好像也不是很大),有些对称加密存在安全隐患(aes cbc 字节翻转攻击)。

假如现在我想做一个适用于 web 和 native app 的 api 服务,该如何选择认证方式?还有如果使用基于 token 的认证方式, token 的设计有没有什么比较好的解决方案?

32195 次点击
所在节点    程序员
43 条回复
markocen
2016-05-07 09:51:16 +08:00
token 的优点是 web server 上不需要保存用户的信息,更容易做分布式或者 web farm
chaegumi
2016-08-16 09:55:43 +08:00
我是搞 php 的,我看不懂官网的 jwt 示例

```java

import org.pac4j.http.profile.HttpProfile;
import org.pac4j.jwt.profile.JwtGenerator;
...
JwtGenerator<HttpProfile> g = new JwtGenerator<>("<SIGNING_SECRET>", "<ENCRYPTION_SECRET>");
HttpProfile profile = new HttpProfile();
profile.setId("<PRINCIPAL_ID>");
final String token = g.generate(profile);
System.out.println(token);

```

那几个尖括号里边的内容,能帮我举例子吗?
xuxueli
2018-04-11 14:32:38 +08:00
基于 sesssion 常用于 web 接入(登陆凭证存储在 cookie 中);基于 Token 常用于 APP 接入(登陆凭证需要主动存储,如 sqlite 中);

可以了解下 XXL-SSO 啊,支持两种接入方式:

http://www.xuxueli.com/xxl-sso/

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/276207

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX