日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

springboot entity date_SpringBoot+JWT实战(附源码)

發(fā)布時(shí)間:2023/12/2 javascript 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 springboot entity date_SpringBoot+JWT实战(附源码) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

SpringBoot集成JWT

首先我們搭建好SpringBoot框架,SpringBoot環(huán)境準(zhǔn)備就緒。接下來執(zhí)行以下操作:

1.引入依賴

引入JWT依賴,由于是基于Java,所以需要的是java-jwt。

<dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>3.5.0</version> </dependency>

2.自定義注解

在這一步,我們?cè)赼nnotation包下定義一個(gè)用戶需要登錄才能進(jìn)行其他接口訪問等一系列操作的注解TokenRequired。

`@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface TokenRequired {boolean required() default true; }

@Target旨意為我們自定義注解@TokenRequired的作用目標(biāo),因?yàn)槲覀儽敬巫⒔獾淖饔媚繕?biāo)為方法層級(jí),因此使用 ElementType.METHOD。

@Retention旨意為我們自定義注解 @TokenRequired的保留位置,@TokenRequired的保留位置被定義為RetentionPolicy.RUNTIME這種類型的注解將被JVM保留,他能在運(yùn)行時(shí)被JVM或其他使用反射機(jī)制的代碼所讀取和使用。

3.定義實(shí)體類

在entity包中,我們使用lombok,簡(jiǎn)單自定義一個(gè)實(shí)體類User。

`@Data @AllArgsConstructor @NoArgsConstructor public class User {String Id;String username;String password; }

4.定義一個(gè)JWT工具類

在這一步,我們?cè)趗til包下面創(chuàng)建一個(gè)JwtUtil工具類,用于生成token和校驗(yàn)token。

`public class JwtUtil {//過期時(shí)間15分鐘private static final long EXPIRE_TIME = 15*60*1000;//生成簽名,15分鐘后過期public static String sign(String username,String userId,String password){//過期時(shí)間Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);//使用用戶密碼作為私鑰進(jìn)行加密Algorithm algorithm = Algorithm.HMAC256(password);//設(shè)置頭信息HashMap<String, Object> header = new HashMap<>(2);header.put("typ", "JWT");header.put("alg", "HS256");//附帶username和userID生成簽名return JWT.create().withHeader(header).withClaim("userId",userId).withClaim("username",username).withExpiresAt(date).sign(algorithm);}//校驗(yàn)tokenpublic static boolean verity(String token,String password){try {Algorithm algorithm = Algorithm.HMAC256(password);JWTVerifier verifier = JWT.require(algorithm).build();verifier.verify(token);return true;} catch (IllegalArgumentException e) {return false;} catch (JWTVerificationException e) {return false;}} }

5.業(yè)務(wù)校驗(yàn)并生成token

在service包下,我們創(chuàng)建一個(gè)UserService,并定義一個(gè)login方法,用于做登錄接口的業(yè)務(wù)層數(shù)據(jù)校驗(yàn),并調(diào)取JwtUtil中方法生成token。

`@Service("UserService") public class UserService {@AutowiredUserMapper userMapper;public String login(String name, String password) {String token = null;try {//校驗(yàn)用戶是否存在User user = userMapper.findByUsername(name);if(user == null){ResultDTO.failure(new ResultError(UserError.EMP_IS_NULL_EXIT));}else{//檢驗(yàn)用戶密碼是否正確if(!user.getPassword().equals(password)){ResultDTO.failure(new ResultError(UserError.PASSWORD_OR_NAME_IS_ERROR));}else {// 生成token,將 user id 、userName保存到 token 里面token = JwtUtil.sign(user.getUsername(),user.getId(),user.getPassword());}}} catch (Exception e) {e.printStackTrace();}return token;} }

Algorithm.HMAC256():使用HS256生成token,密鑰則是用戶的密碼,唯一密鑰的話可以保存在服務(wù)端。withAudience()存入需要保存在token的信息,這里我把用戶ID存入token中。

6.定義攔截器

接下來我們需要寫一個(gè)攔截器去獲取token并驗(yàn)證token。

`public class AuthenticationInterceptor implements HandlerInterceptor {@AutowiredUserService userService;@Overridepublic boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {// 從 http 請(qǐng)求頭中取出 tokenString token = httpServletRequest.getHeader("token");// 如果不是映射到方法直接通過if(!(object instanceof HandlerMethod)){return true;}HandlerMethod handlerMethod=(HandlerMethod)object;Method method=handlerMethod.getMethod();//檢查有沒有需要用戶權(quán)限的注解if (method.isAnnotationPresent(TokenRequired.class)) {TokenRequired userLoginToken = method.getAnnotation(TokenRequired.class);if (userLoginToken.required()) {// 執(zhí)行認(rèn)證if (token == null) {throw new RuntimeException("無token,請(qǐng)重新登錄");}// 獲取 token 中的 user idString userId;try {userId = JWT.decode(token).getClaim("userId").asString();} catch (JWTDecodeException j) {throw new RuntimeException("401");}User user = userService.findUserById(userId);if (user == null) {throw new RuntimeException("用戶不存在,請(qǐng)重新登錄");}// 驗(yàn)證 tokentry {if(!JwtUtil.verity(token,user.getPassword())){throw new RuntimeException("無效的令牌");}} catch (JWTVerificationException e) {throw new RuntimeException("401");}return true;}}return true;}@Overridepublic void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {}@Overridepublic void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {} }

AuthenticationInterceptor攔截器實(shí)現(xiàn)了HandlerInterceptor接口的三個(gè)方法:

  • boolean preHandle ():
  • 預(yù)處理回調(diào)方法,實(shí)現(xiàn)處理器的預(yù)處理,第三個(gè)參數(shù)為響應(yīng)的處理器,自定義Controller返回值,返回值為true會(huì)調(diào)用下一個(gè)攔截器或處理器,或者接著執(zhí)行postHandle()和afterCompletion();false表示流程中斷,不會(huì)繼續(xù)調(diào)用其他的攔截器或處理器,中斷執(zhí)行。

    2.void postHandle():

    后處理回調(diào)方法,實(shí)現(xiàn)處理器的后處理(DispatcherServlet進(jìn)行視圖返回渲染之前進(jìn)行調(diào)用),此時(shí)我們可以通過modelAndView對(duì)模型數(shù)據(jù)進(jìn)行處理或?qū)σ晥D進(jìn)行處理,modelAndView也可能為null。

    3.void afterCompletion():

    整個(gè)請(qǐng)求處理完畢回調(diào)方法,該方法也是需要當(dāng)前對(duì)應(yīng)的Interceptor的preHandle()的返回值為true時(shí)才會(huì)執(zhí)行,也就是在DispatcherServlet渲染了對(duì)應(yīng)的視圖之后執(zhí)行。用于進(jìn)行資源清理。

    該攔截器的執(zhí)行流程為:

  • 從 http 請(qǐng)求頭中取出 token;
  • 檢查有沒有需要用戶權(quán)限的注解,如果需要,檢驗(yàn)token是否為空;
  • 如果token不為空,查詢用戶信息并校驗(yàn)token;
  • 校驗(yàn)通過,則進(jìn)行業(yè)務(wù)訪問處理,校驗(yàn)失敗則返回token失效信息。
  • 7.配置攔截器

    在配置類上添加了注解@Configuration,標(biāo)明了該類是一個(gè)配置類并且會(huì)將該類作為一個(gè)SpringBean添加到IOC容器內(nèi)。

    `@Configuration public class InterceptorConfig implements WebMvcConfigurer {@Beanpublic AuthenticationInterceptor authenticationInterceptor() {return new AuthenticationInterceptor();}@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 將我們上步定義的實(shí)現(xiàn)了HandlerInterceptor接口的攔截器實(shí)例authenticationInterceptor添加InterceptorRegistration中,并設(shè)置過濾規(guī)則,所有請(qǐng)求都要經(jīng)過authenticationInterceptor攔截。registry.addInterceptor(authenticationInterceptor()).addPathPatterns("/**");} }

    WebMvcConfigurer接口是Spring內(nèi)部的一種配置方式,采用JavaBean的形式來代替?zhèn)鹘y(tǒng)的xml配置文件來實(shí)現(xiàn)基本的配置需要。

    InterceptorConfig內(nèi)的addInterceptor需要一個(gè)實(shí)現(xiàn)HandlerInterceptor接口的攔截器實(shí)例,addPathPatterns方法用于設(shè)置攔截器的過濾路徑規(guī)則。

    在addInterceptors方法中,我們將第6步定義的實(shí)現(xiàn)了HandlerInterceptor接口的攔截器實(shí)例authenticationInterceptor,添加至InterceptorRegistration中,并設(shè)置過濾路徑。現(xiàn)在,我們所有請(qǐng)求都要經(jīng)過authenticationInterceptor的攔截,攔截器authenticationInterceptor通過preHandle方法的業(yè)務(wù)過濾,判斷是否有@TokenRequired 來決定是否需要登錄。

    8.定義接口方法并添加注解

    `@RestController @RequestMapping("user") public class UserController {@AutowiredUserService userService;/*** 用戶登錄* @param user* @return*/@PostMapping("/login")public ResultDTO login( User user){String token = userService.login(user.getUsername(), user.getPassword());if (token == null) {return ResultDTO.failure(new ResultError(UserError.PASSWORD_OR_NAME_IS_ERROR));}Map<String, String> tokenMap = new HashMap<>();tokenMap.put("token", token);return ResultDTO.success(tokenMap);}@TokenRequired@GetMapping("/hello")public String getMessage(){return "你好哇,我是小碼仔";} } 不加注解的話默認(rèn)不驗(yàn)證,登錄接口一般是不驗(yàn)證的。所以我在getMessage()中加上了登錄注解,說明該接口必須登錄獲取token后,在請(qǐng)求頭中加上token并通過驗(yàn)證才可以訪問。

    請(qǐng)求驗(yàn)證

    我在代碼中對(duì)getMessage()添加了@TokenRequired注解,此刻訪問該方法時(shí)必須要通過登錄拿取到token值,并在請(qǐng)求頭中添加token才可以訪問。我們現(xiàn)在做以下校驗(yàn):

  • 直接訪問,不在請(qǐng)求頭里添加token:
  • 如上圖所示,請(qǐng)求結(jié)果顯示:無token,請(qǐng)重新登錄

    2.訪問登錄接口,獲取token,并在請(qǐng)求頭中添加token信息:


    此時(shí),訪問成功

    3.15分鐘后,token失效,我們?cè)俅卧谡?qǐng)求頭中添加token信息訪問:

    此時(shí)token已失效,返回:無效的令牌。

    總結(jié)

    回顧一下本次JWT使用的基本業(yè)務(wù)判斷流程:

  • 用戶訪問頁面,前端請(qǐng)求相關(guān)接口,經(jīng)過攔截器,攔截器中從 http 請(qǐng)求頭中取出 token;
  • 檢查該接口有沒有@TokenRequired注解,如果沒有,直接放行;如果有,檢驗(yàn)token是否為空;
  • 如果token為空,訪問失敗;token不為空,則查詢用戶信息并校驗(yàn)token;
  • 校驗(yàn)通過,則進(jìn)行業(yè)務(wù)訪問處理,校驗(yàn)失敗則返回token失效信息。
  • 不足之處:本次集成只是做一個(gè)簡(jiǎn)單的JWT使用介紹,沒有實(shí)現(xiàn)token的過期刷新機(jī)制,此種情況下用戶每隔15分鐘就需要重新登錄一次,如果在實(shí)際生產(chǎn)環(huán)境中使用,可能會(huì)被用戶打死,因此實(shí)際開發(fā)中并不推薦。

    關(guān)于token的刷新機(jī)制,將在下篇文章中為大家解讀并附上源碼。

    本次集成代碼地址:https://github.com/bailele1995/springboot-jjwt.git
    來源:https://juejin.im/post/5ea27c5be51d4546c27bdf94?utm_source=tuicool&utm_medium=referral

    總結(jié)

    以上是生活随笔為你收集整理的springboot entity date_SpringBoot+JWT实战(附源码)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。