怎么做校園表白墻網(wǎng)站怎么在網(wǎng)上做網(wǎng)絡營銷
為實現(xiàn)Jwt簡單的權限管理,我們需要用Jwt工具來生成token,也需要用Jwt來解碼token,同時需要添加Jwt攔截器來決定放行還是攔截。下面來實現(xiàn):
1、gradle引入Jwt、hutool插件
implementation 'com.auth0:java-jwt:3.10.3'implementation 'cn.hutool:hutool-all:5.3.7'
2、Jwt工具類,提供靜態(tài)方法生成token,和根據(jù)請求攜帶的token查找user信息
package com.zzz.simple_blog_backend.utils;import ......@Component
public class JwtTokenUtils {@Autowiredprivate UserService userService;private static UserService userServiceStatic;@PostConstruct//在spring容器初始化后執(zhí)行該方法public void setUserService() {userServiceStatic = userService;}//生成Tokenpublic static String genToken(String userId,String passwordSign) {return JWT.create().withAudience(userId)//放入載荷.withExpiresAt(DateUtil.offsetHour(new Date(), 2))//2小時后過期.sign(Algorithm.HMAC256(passwordSign));//密碼簽名作為密鑰}//通過token獲取當前登錄用戶信息public static User getCurrentUser() {String token = null;HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();//1、獲取tokentoken = request.getHeader("token");if (StrUtil.isBlank(token)) {token = request.getParameter("token");}if (StrUtil.isBlank(token)) {throw new RuntimeException("沒有token,請重新登錄");}String userId;User user;try {userId = JWT.decode(token).getAudience().get(0);} catch (Exception e) {throw new RuntimeException("token驗證失敗,請重新登錄!!!");}user = userServiceStatic.findById(Integer.parseInt(userId));if(user==null) {throw new RuntimeException("用戶id不存在,請重新登錄!!!");}//3、用密碼簽名,解碼判斷tokentry {JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();jwtVerifier.verify(token);} catch (JWTVerificationException e) {throw new CustomException(001, "token驗證失敗,請重新登錄!!!");}return user;}
}
3、Jwt攔截器
SpringBoot添加攔截器,excludePathPatterns
可以指定不攔截的頁面,RestController
指定了請求前綴,控制器類要用@RestController
代替@Controller
,addInterceptor
添加了jwtInterceptor
攔截器。
package com.zzz.simple_blog_backend.config;import ...@Configuration
public class WebConfig implements WebMvcConfigurer{@Autowiredprivate JwtInterceptor jwtInterceptor;@Overridepublic void configurePathMatch(PathMatchConfigurer configurer) {//指定restcontroller統(tǒng)一接口前綴configurer.addPathPrefix("/api", clazz -> clazz.isAnnotationPresent(RestController.class));}@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 加自定義攔截器 給特定請求放行registry.addInterceptor(jwtInterceptor).addPathPatterns("/api/**").excludePathPatterns("/api/user/login","/api/user/register");}
}
仔細的童靴會發(fā)現(xiàn)JwtTokenUtils.getCurrentUser()
方法和JwtInterceptor
的攔截方法很像,主要區(qū)別就在if(user.getRole()!=0)
的判斷。所以JwtInterceptor
只會給管理員放行,如果需要給普通用戶放行而未登錄用戶不放行,那請求路徑先添加到excludePathPatterns
,并且控制類對應的響應方法第一句就先調(diào)用JwtTokenUtils.getCurrentUser()
判斷是否用戶已登錄。
package com.zzz.simple_blog_backend.config;import ......@Component
public class JwtInterceptor implements HandlerInterceptor{@Autowiredprivate UserService userService;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {//1、獲取tokenString token = request.getHeader("token");if (StrUtil.isBlank(token)) {token = request.getParameter("token");}if (StrUtil.isBlank(token)) {throw new RuntimeException("沒有token,請重新登錄");}//2、開始認證 解碼token,獲得userIdString userId;User user;try {userId = JWT.decode(token).getAudience().get(0);} catch (Exception e) {throw new RuntimeException("token驗證失敗,請重新登錄!!!");}user = userService.findById(Integer.parseInt(userId));if(user==null) {throw new RuntimeException("用戶id不存在,請重新登錄!!!");}if(user.getRole()!=0) {throw new RuntimeException("非管理員賬號,無權訪問!!!");}//3、用密碼簽名,解碼判斷tokentry {JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();jwtVerifier.verify(token);} catch (JWTVerificationException e) {throw new RuntimeException("token驗證失敗,請重新登錄!!!");}//token驗證成功,放行return true;
// return HandlerInterceptor.super.preHandle(request, response, handler);}
}
4、前后端登錄操作
登錄后 后端返回帶token不帶密碼的user數(shù)據(jù)
@PostMapping("user/login")@ResponseBodypublic CommonResult<Object> login(@RequestBody User user){user = userService.findByUsernameAndPassword(user);if (user == null) {return CommonResult.failed(001, Message.createMessage("用戶名或密碼錯誤!!!"));} else {//生成用戶對應的TokenString token = JwtTokenUtils.genToken(user.getId().toString(), user.getPassword());user.setToken(token);//不傳輸密碼user.setPassword("");return CommonResult.success(user);}}
前端保存帶token的user
//axios的post請求成功后操作localStorage.setItem("user",JSON.stringify(response.data.data));//保存用戶信息
5、前端每次請求都攜帶token信息
假設已安裝axios,Axios.interceptors.request
攔截用戶所有請求,添加token信息后再發(fā)送請求,這樣后端就可以判斷了。
import Axios from 'axios'Vue.prototype.$http = Axios;
//添加向后端發(fā)起請求的服務器地址前綴
Axios.defaults.baseURL=AIOS_BASE_URL; // "http://127.0.0.1/api"
//設置請求超時時間
Axios.defaults.timeout=5000;//axios攔截器
//對接口request攔截
Axios.interceptors.request.use(function(config){//發(fā)起增刪改查請求時,帶上token認證var user = localStorage.getItem("user");if(user){config.headers["token"] = JSON.parse(user).token;}return config;
})
//攜帶證書 session id 跨域請求的話需要
Axios.defaults.withCredentials = true
總結
Jwt實現(xiàn)權限管理的原理是登錄成功后 后端端生成token密鑰,隨著用戶信息發(fā)送給客戶端,客戶端接受并保存信息到本地localStorage。以后每次需要權限驗證時,根據(jù)客戶端返回的攜帶token信息,后端進行攔截并解碼校驗,通過則放行,否則拋異常。如果要拋異常時,返回錯誤信息給前端,請看鏈接。