在我们日常使用的网站里面,我们每点开一个链接,就会获取一系列的信息。
有些信息是公共的,但是有些信息是属于某一类人或者是某一用户的,在获取这些信息的时候,我们需要验证获取者的信息,用的最多的就是token技术。
验证用户信息,可以在每一次获取数据的时候,将用户名和密码之类的信息去数据库查询比对,但是网页的请求太过于频繁,每次都查数据库会对服务器造成很大的压力。
在我们的古装电视剧里面,经常会看到一位侠客或者一位官员需要进出一些重要场所时,会对外面的侍卫掏出一枚令牌,用以表明他的身份和权力,不需要去上报核查来者身份,也能放行。
因为使用方便,互联网采用了同样的思想,提出了令牌(token)的概念。
Token本质上是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。
JWT是一种基于json的开发标准,用于签发令牌(token)。
在JWT标准下生成的token,由三个部分组成:头部、载荷、签证。
声明类型(jwt)和token的加密算法(一般使用HMAC SHA256)。
签发人;
过期时间;
主题;
受众;
生效时间;
签发时间;
编号;
除了这些,我们还可以自定义字段,比如带上用户的账号和名字等。
首先需要指定一个密钥,这个是服务器知道的,不能给用户,然后按照头部里面指定的算法生成签名。最后将头部、载荷和签名拼接起来,就构成了token。
package com.JavaWebServer.util;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* @author zm
* @desc 使用token验证用户是否登录
**/
public class JWTUtils {
//设置过期时间
private static final long EXPIRE_DATE = 30 * 60 * 1000;
//token秘钥
private static final String TOKEN_SECRET = "这里是密钥";
private static final String CLASS_NAME = JWTUtils.class.getName();
// 指定格式化格式
private static SimpleDateFormat f = new SimpleDateFormat("MM-dd HH:mm:ss");
public static String creatToken(String email) {
String token;
try {
//过期时间
Date date = new Date(System.currentTimeMillis() + EXPIRE_DATE);
//秘钥及加密算法
Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
//设置头部信息
Map<String, Object> header = new HashMap<>();
header.put("typ", "JWT");
header.put("alg", "HS256");
//携带username,password信息,生成签名
token = JWT.create()
.withIssuedAt(new Date(System.currentTimeMillis()))
.withExpiresAt(date)
.withHeader(header)
.withClaim("email", email)
.sign(algorithm);
} catch (Exception e) {
e.printStackTrace();
return null;
}
return token;
}
/**
* @return
* @desc 验证token,返回token里的信息
* @params [token]需要校验的串
*/
public static Map<String, Object> getToken(HttpServletRequest request) {
final Map<String, Object> map = new HashMap<>();
String token = null;
final Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals("token")) {
token = cookie.getValue();
break;
}
}
}
if (token == null) return null;
try {
Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
JWTVerifier verifier = JWT.require(algorithm).build();
DecodedJWT jwt = verifier.verify(token);
map.put("email", jwt.getClaim("email").asString());
map.put("issuedAt", f.format(jwt.getIssuedAt()));
map.put("expiresAt", f.format(jwt.getExpiresAt()));
return map;
} catch (Exception e) {
// e.printStackTrace();
return null;
}
}
}
使用bootstrap的 nav-pills 样式:
<ul class="nav nav-pills nav-stacked">
未登录前我们显示登陆注册按钮,隐藏用户信息按钮。
登录成功后我们显示用户信息按钮,隐藏登陆注册按钮。
因为登录成功后,我们服务器会生成一个token给客户端。
我们主页每一次加载,向服务器发起一次请求,验证浏览器是否存在token以及token是否正确。
根据token里面的用户信息,然后向数据库查询用户的信息,主页加载其对应的用户信息,并显示。
function verify() {
//定义一个全局变量来接受$post的返回值
var result = false;
//用ajax的“同步方式”调用一般处理程序
$.ajax({
url: '/verify',
async: false,//改为同步方式
type: "POST",
success: function (res) {
//如果token解析成功
if (res['data'] != null)
result = true;
}
});
return result;
}
//如果token正确
if (verify()) {
// 显示头像
$('#user-center-button').attr('style', '');
//隐藏登陆注册按钮
$('#register-button').attr('style', 'display:none');
// 获取用户基本信息
$.post('/getUserProFileInfo',
function (res) {
if (res['data'] != null) {
//加载到网页界面
$('.profile-fans-count').html(res['data']['fans_count']);
$('.profile-follow-count').html(res['data']['follow_count']);
$('.profile-nickname').html(res['data']['nickname']);
}
})