token在现在用的特别多,但网上基本上都是在springboot框架中配置。这里记录一下SSM框架中配置
在pom.xml中导入需要的依赖jar包,点击刷新下载
<dependency>
<groupId>com.auth0groupId>
<artifactId>java-jwtartifactId>
<version>3.10.0version>
dependency>
一般来说,在项目的文件夹下创建一个文件夹utils,在下面创建一个java文件JWTUtils。
private static final long EXPIRE_TIME = 15 * 60 * 1000;//代表过期时间(15分钟),前端这么长时间没操作,就过期了,需要重新登录。
private static final String TOKEN_SECRET = “f26e587c28064d0e855e72c0a6a0e618”;//代表密钥,随便自己设置,越复杂越难被破解
public static String sign(String username,String userId) //生成token,用户登录之后就调用这个方法。输入两个参数,一般是账号和密码
public static boolean verify(String token)//验证token,在每次访问接口的时候使用,一般在拦截器中使用(拦截器后面有)
public static String getUsername(String token) //通过token获取用户名
public static String getUserId(String token)//通过token获取用户id
一般一个设置为账号,一个设置为密码
import com.auth0.jwt.*;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* Java web token 工具类
*
*/
public class JWTUtils {
/**
* 过期时间一天,
* TODO 正式运行时修改为15分钟
*/
private static final long EXPIRE_TIME = 15 * 60 * 1000;
/**
* token私钥
*/
private static final String TOKEN_SECRET = "f26e587c28064d0e855e72c0a6a0e618";
/**
* 校验token是否正确
*
* @param token 密钥
* @return 是否正确
*/
public static boolean verify(String token) {
try {
Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
JWTVerifier verifier = JWT.require(algorithm)
.build();
DecodedJWT jwt = verifier.verify(token);
return true;
} catch (Exception exception) {
return false;
}
}
/**
* 获得token中的信息无需secret解密也能获得
*
* @return token中包含的用户名
*/
public static String getUsername(String token) {
try {
DecodedJWT jwt = JWT.decode(token);
return jwt.getClaim("loginName").asString();
} catch (JWTDecodeException e) {
return null;
}
}
/**
* 获取登陆用户ID
* @param token
* @return
*/
public static String getUserId(String token) {
try {
DecodedJWT jwt = JWT.decode(token);
return jwt.getClaim("userId").asString();
} catch (JWTDecodeException e) {
return null;
}
}
/**
* 生成签名,15min后过期
*
* @param username 用户名
* @return 加密的token
*/
public static String sign(String username,String userId) {
Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);// 私钥及加密算法
Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
// 设置头部信息
Map header = new HashMap<>(2);
header.put("typ", "JWT");
header.put("alg", "HS256");
// 附带username,userId信息,生成签名
return JWT.create()
.withHeader(header)
.withClaim("loginName", username)
.withClaim("userId",userId)
.withExpiresAt(date)
.sign(algorithm);
}
}
token的作用是验证用户的登录信息,前端的每次http请求都需要检测用户是否登录。因此,需要编写拦截器的代码。在项目下面创建一个文件夹 interceptor,在里面创建TokenInterceptor.java文件,放入代码。
最重要的是preHandle方法,因为我前端传过来的token的名字叫sessionValue,所以我获取的是sessionValue,如果前端传来的token名字叫token,把下面代码String token=request.getParameter(“sessionValue”);中的sessionValue改为token。
如果通过验证,就为true,进入后端controller方法,如果没有通过,返回前端false。
如果没有token值传来,就是进行页面跳转到登陆页面。
import com.alibaba.fastjson.JSONObject;
import com.lostAndFound.utils.JWTUtils;
import io.swagger.annotations.ApiResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
/**
* 此处拦截器
*/
public class TokenInterceptor implements HandlerInterceptor {
/**
* 拦截器和过滤器的区别
* 1.拦截器针对访问控制器进行拦截
* 及 @RequestMapping(value = {"/test"})
* 简而言说就是访问方法的url
* 应用:可以作为权限的判断,
* 2.过滤器则是针对全局的请求
* 包括:css/js/html/jpg/png/git/...
* 及静态文件
*
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
response.setCharacterEncoding("utf-8");
String token=request.getParameter("sessionValue");
//Cookie cookie=getCookieByName(request,"_COOKIE_NAME");
//如果已经登录,不拦截
if (null != token) {
//验证token是否正确
boolean result = JWTUtils.verify(token);
System.out.println("是否通过拦截器:"+result);
if (!result) {
return false;
}
return true;
}
//如果没有登录,则跳转到登录界面
else {
//重定向 第一种 调用控制器 方法
response.sendRedirect(request.getContextPath() + "/login");
//重定向 第二种 重定向方法
// request.getRequestDispatcher("WEB-INF/jsp/login.jsp").forward(request, response);
// System.out.println(request.getContextPath());
return false;
/**
* 以下是为了登录成功后返回到刚刚的操作,不跳到主界面
* 实现:通过将请求URL保存到session的beforePath中,然后在登录时判断beforePath是否为空
*/
}
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
/**
* 根据名字获取cookie
*
* @param request
* @param name cookie名字
* @return
*/
public static Cookie getCookieByName(HttpServletRequest request, String name) {
Map<String, Cookie> cookieMap = ReadCookieMap(request);
if (cookieMap.containsKey(name)) {
Cookie cookie = cookieMap.get(name);
return cookie;
} else {
return null;
}
}
/**
* 将cookie封装到Map里面
*
* @param request
* @return
*/
private static Map<String, Cookie> ReadCookieMap(HttpServletRequest request) {
Map<String, Cookie> cookieMap = new HashMap<String, Cookie>();
Cookie[] cookies = request.getCookies();
if (null != cookies) {
for (Cookie cookie : cookies) {
cookieMap.put(cookie.getName(), cookie);
}
}
return cookieMap;
}
/**
* 返回信息给客户端
*
* @param response
* @param out
* @param apiResponse
*/
private void responseMessage(HttpServletRequest request, HttpServletResponse response, PrintWriter out, ApiResponse apiResponse) throws IOException {
response.setContentType("application/json; charset=utf-8");
out.print(JSONObject.toJSONString(apiResponse));
out.flush();
out.close();
}
token的作用是验证用户的登录信息,前端的每次http请求都需要检测用户是否登录,但是登录的时候没有token,所以需要放行token。系统不知道什么时候需要拦截,什么时候不拦截。因此需要配置需要拦截的地址。配置在spring-mvc.xml文件中。(也有可能不叫spring-mvc.xml,不过名字一般和mvc,web有关,比如spring-web,在resources文件夹下面找找)
其中
告诉系统拦截的的位置(前面第三点的位置)
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/admin/**"/>
<mvc:exclude-mapping path="/admin/checkLogin"/>
<bean class="com.lostAndFound.interceptor.TokenInterceptor">bean>
mvc:interceptor>
mvc:interceptors>
登录的方法,前端传来账号密码,首先判断账号密码是否正确,正确创建token并返回,错误返回false
其他业务方法基本相同,因为在拦截器已经验证过token是否有效了,这里就不需要验证了。
@RequestMapping(value = "/checkLogin")
@ResponseBody
public String checkLogin(@RequestParam() String username, @RequestParam() String password){
Admin admin=new Admin();
admin.setId(Integer.parseInt(username));
admin.setPassword(password);
boolean bool = adminService.checkAdminLog(admin);
System.out.println("密码是否正确:"+bool);
if(bool){
//返回token值
String token = JWTUtils.sign(username, password);
System.out.println(token);
return token;
}
else{
return "false";
}