如何使用JWT來實現單點登陸功能

咱們平時本身開發項目,分佈式的結構時,訪問量不大,可是又不想搭建redis服務器,這時我以爲jwt不錯.html

我的理解,jwt就是相似於一把鎖和鑰匙,客戶來租房(登陸),咱們須要給他進來(第一次登陸)登記消息,配把鑰匙給他(使用jwt生成一個token,存放在用的cookie中),咱們這邊也須要配置一把咱們需求的鎖(jwt的生成token,解析token規則咱們來寫),接下來看下我最近運用jwt的小實例(該項目由springboot2.x搭建).前端

首先須要的maven工程pom.xml文件中添加依賴web

<!-- JWT相關 -->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.7.0</version>
        </dependency>

 

自定義一個攔截類,用戶沒有鑰匙的都須要登陸(jwt生成的token)redis

/** * 自定義登陸攔截器 */
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中須要配置一個配置類,註冊咱們的自定義配置類spring

/** *自定義攔截類的配置類 */ @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下面會貼出來,方便你們複製json

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; } }
相關文章
相關標籤/搜索