1. 程式人生 > >Jwt在javaweb項目中的應用核心步驟解讀

Jwt在javaweb項目中的應用核心步驟解讀

policy quest sta entity lose lang get actor ole

1.引入jwt依賴

       <!--引入JWT依賴,由於是基於Java,所以需要的是java-jwt-->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>
        <dependency>
<groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.4.0</version> </dependency>
2.創建兩個註解,PassToken和UserLoginToken,用於在項目開發中,如果需要權限校驗就標註userlogintoken,如果訪問的資源不需要權限驗證則正常編寫不需要任何註解,如果用的的請求時登錄操作,在用戶登錄的方法上增加passtoken註解。
passtoken
package com.pjb.springbootjjwt.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * @author jinbin * @date 2018-07-08 20:38 */ @Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME)
public @interface PassToken { boolean required() default true; }
userlogintoken
package com.pjb.springbootjjwt.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author jinbin
 * @date 2018-07-08 20:40
 */
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface UserLoginToken {
    boolean required() default true;
}
註解解析:從上面我們新建的兩個類上我們可以看到主要的等學習到的就四點
第一:如何創建一個註解
第二:在我們自定義註解上新增@Target註解(註解解釋:這個註解標註我們定義的註解是可以作用在類上還是方法上還是屬性上面)
第三:在我們自定義註解上新增@Retention註解(註解解釋:作用是定義被它所註解的註解保留多久,一共有三種策略,SOURCE 被編譯器忽略,CLASS  註解將會被保留在Class文件中,但在運行時並不會被VM保留。這是默認行為,所有沒有用Retention註解的註解,都會采用這種策略。RUNTIME  保留至運行時。所以我們可以通過反射去獲取註解信息。
第四:boolean required() default true;  默認required() 屬性為true
3.服務端生成Token

技術分享圖片

4.服務端攔截請求驗證Token的流程

第一步:創建攔截器,方法執行之前執行攔截

技術分享圖片

第二步:判斷是否請求方法

技術分享圖片

第三步:判斷方法是否是登錄方法

技術分享圖片

第三步:判斷是否為需要權限驗證的方法

技術分享圖片

5.在項目中的應用

技術分享圖片

附上攔截器源代碼

技術分享圖片
package com.pjb.springbootjjwt.interceptor;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.pjb.springbootjjwt.annotation.PassToken;
import com.pjb.springbootjjwt.annotation.UserLoginToken;
import com.pjb.springbootjjwt.entity.User;
import com.pjb.springbootjjwt.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.HandlerMethod;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;


/**
 * @author jinbin
 * @date 2018-07-08 20:41
 */
public class AuthenticationInterceptor implements HandlerInterceptor {

    @Autowired
    UserService userService;

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {

        // 從 http 請求頭中取出 token
        String token = httpServletRequest.getHeader("token");
        // 如果不是映射到方法直接通過
        if (!(object instanceof HandlerMethod)) {
            return true;
        }


        HandlerMethod handlerMethod = (HandlerMethod) object;
        Method method = handlerMethod.getMethod();
        //檢查是否有passtoken註釋,有則跳過認證
        if (method.isAnnotationPresent(PassToken.class)) {
            PassToken passToken = method.getAnnotation(PassToken.class);
            if (passToken.required()) {
                return true;
            }
        }


        //檢查有沒有需要用戶權限的註解
        if (method.isAnnotationPresent(UserLoginToken.class)) {
            UserLoginToken userLoginToken = method.getAnnotation(UserLoginToken.class);
            if (userLoginToken.required()) {
                // 執行認證
                if (token == null) {
                    throw new RuntimeException("無token,請重新登錄");
                }
                // 獲取 token 中的 user id
                String userId;
                try {
                    userId = JWT.decode(token).getAudience().get(0);
                } catch (JWTDecodeException j) {
                    throw new RuntimeException("401");
                }
                User user = userService.findUserById(userId);
                if (user == null) {
                    throw new RuntimeException("用戶不存在,請重新登錄");
                }

                // 驗證 token
                JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();

                try {
                    jwtVerifier.verify(token);
                } catch (JWTVerificationException e) {
                    throw new RuntimeException("401");
                }
                return true;
            }
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }


}
View Code

Jwt在javaweb項目中的應用核心步驟解讀