我們平時自己開發項目,分布式的結構時,訪問量不大,但是又不想搭建redis服務器,這時我覺得jwt不錯.
個人理解,jwt就是類似於一把鎖和鑰匙,客戶來租房(登錄),我們需要給他進來(第一次登錄)登記消息,配把鑰匙給他(使用jwt生成一個token,存放在用的cookie中),我們這邊也需要配置一把我們需求的鎖(jwt的生成token,解析token規則我們來寫),接下來看下我最近運用jwt的小實例(該項目由springboot2.x搭建).
首先需要的maven工程pom.xml文件中添加依賴
<!-- JWT相關 -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.7.0</version>
</dependency>
自定義一個攔截類,用戶沒有鑰匙的都需要登錄(jwt生成的token)
/** * 自定義登錄攔截器 */
public class LoginIntercepter implements HandlerInterceptor { private static final Gson gson = new Gson(); /** * 進入controller的攔截 * @param request * @param response * @param handler * @return * @throws Exception */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token =""; //判斷用戶cookie中有無token
Cookie[] ctoken = request.getCookies(); if(ctoken!=null){ for(Cookie ftoken: ctoken){ if(ftoken.getName().equals("token")){ token = ftoken.getValue(); } } } if (!token.isEmpty()){ //3.如果用戶有token,則進行jwt解密
Claims claims = JWTUtils.checkToken(token); if (claims != null){ //4.不為空,則說明用戶已登錄,獲取用戶id,姓名,保存在request中的Attribute作用域中,這樣controller就可以取到值
String signatureFile = (String) claims.get("signatureFile"); String email = (String) claims.get("email"); request.setAttribute("user_signatureFile",signatureFile); request.setAttribute("user_email",email); //5.放行
return true; } } //6.返回錯誤信息給前端 //sendMessage(response, JsonData.buildError("請登錄")); //response.flushBuffer();
response.sendRedirect("sign_in.html"); return false; } /** * 發送錯誤信息給前端 */
public static void sendMessage(HttpServletResponse response, Object obj) throws IOException { response.setContentType("application/json;charset:utf-8"); PrintWriter writer = response.getWriter(); writer.print(gson.toJson(obj)); writer.close(); //需要刷新一下,怕有緩存
response.flushBuffer(); } }
springboot中需要配置一個配置類,注冊我們的自定義配置類
/** *自定義攔截類的配置類 */ @Configuration public class InterceptConfig implements WebMvcConfigurer { //注冊一個我們登錄的攔截類
@Override public void addInterceptors(InterceptorRegistry registry) { //我們需要排除登錄,和注冊的攔截(特別注意,我們還需要取消攔截靜態資源的訪問)
String[] exclude = new String[]{"/sign_in.html","/sign_up.html","/static/**","/assets/**","/login","/user_register"}; //1.需要對我們自定義的攔截器進行注冊
registry.addInterceptor(new LoginIntercepter()).addPathPatterns("/**").excludePathPatterns(exclude);//攔截路徑
WebMvcConfigurer.super.addInterceptors(registry); } }
前面我們攔截類寫好了,用戶被攔截后會跳轉到登錄或者注冊界面,這時,在我們的控制類中,我們需要根據表單提交的信息,生成相應的token,下面是控制類的重要代碼,里面用到的JWTUtils下面會貼出來,方便大家復制
int save = userService.save(user); if (save == 1) { //return JsonData.buildSuccess(user,"注冊成功"); //使用jwt來將用戶信息生成token的字符串
String token = JWTUtils.geneToken(user); //將token保存到cookie中去,並且設置時間為半個鍾
Cookie cookie = new Cookie("token",token); cookie.setMaxAge(60*30); response.addCookie(cookie); response.sendRedirect("/index"); //return JsonData.buildError("注冊成功,即將跳轉到首頁!",0);
} else { return new JsonData(-1,null,"注冊失敗,請重試"); }
用戶登錄后,cookie中會被保存我們jwt生成的token,我這里設置半個鍾有效期,在上面的自定義攔截器中,用戶訪問頁面,會先向用戶拿取token,有token的話,會被解析出相應信息,並且直接跳入首頁,無須登錄.接下來下面是JWTUtils
public class JWTUtils { public static final String SUBJECT = "ouyan"; //編寫發布者
public static final int EXPIRE = 1000*60*60*30; //設置過期時間,單位為毫秒,過期時間為半個鍾
public static final String APPSECRET = "axin"; //設置密鑰
/** * 使用jwt生成token */
public static String geneToken(User user){ //先判斷是否為空,為空返回null
if (user == null || user.getSignatureFile() == null || user.getEmail() == null ){ return null; } String token = Jwts.builder().setSubject(SUBJECT).claim("signatureFile",user.getSignatureFile()) .claim("email",user.getEmail()).setIssuedAt(new Date()).setExpiration(new Date(System.currentTimeMillis()+EXPIRE)) .signWith(SignatureAlgorithm.HS256,APPSECRET).compact(); return token; } /** * 校驗密鑰 */
public static Claims checkToken(String token) { try { final Claims claims = Jwts.parser().setSigningKey(APPSECRET) .parseClaimsJws(token).getBody(); return claims; } catch (Exception e) { e.printStackTrace(); System.out.println("出錯啦"); } return null; } }