国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

SpringBoot + Vue前后端分離項(xiàng)目實(shí)戰(zhàn) || 六:Jwt加密整合配置

這篇具有很好參考價(jià)值的文章主要介紹了SpringBoot + Vue前后端分離項(xiàng)目實(shí)戰(zhàn) || 六:Jwt加密整合配置。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

回顧

在之前的系統(tǒng)中,我們利用UUID配合Redis以達(dá)到角色登錄的功能。

當(dāng)前整個(gè)系統(tǒng)存在一個(gè)問題:人為修改token值后,用戶仍然能在前端進(jìn)行數(shù)據(jù)庫(kù)操作,后臺(tái)沒有校驗(yàn)當(dāng)前用戶token就允許一些請(qǐng)求,導(dǎo)致系統(tǒng)存在安全漏洞。

解決方法:Jwt簽名驗(yàn)證。整合Jwt后,前端發(fā)出的請(qǐng)求后端會(huì)先進(jìn)行token驗(yàn)證,然后執(zhí)行操作。

整合Jwt的效果如下:找到token值,然后進(jìn)行修改
SpringBoot + Vue前后端分離項(xiàng)目實(shí)戰(zhàn) || 六:Jwt加密整合配置,spring boot,vue.js,后端

token前加上值123,保存后進(jìn)行一些操作
SpringBoot + Vue前后端分離項(xiàng)目實(shí)戰(zhàn) || 六:Jwt加密整合配置,spring boot,vue.js,后端

此時(shí)點(diǎn)擊頁(yè)面修改按鈕,會(huì)彈出token錯(cuò)誤的信息
SpringBoot + Vue前后端分離項(xiàng)目實(shí)戰(zhàn) || 六:Jwt加密整合配置,spring boot,vue.js,后端

后端也會(huì)記錄token錯(cuò)誤的信息
SpringBoot + Vue前后端分離項(xiàng)目實(shí)戰(zhàn) || 六:Jwt加密整合配置,spring boot,vue.js,后端
現(xiàn)在開始來實(shí)現(xiàn)這個(gè)功能

添加依賴

SpringBoot + Vue前后端分離項(xiàng)目實(shí)戰(zhàn) || 六:Jwt加密整合配置,spring boot,vue.js,后端

Jwt依賴

在pom文件中添加下述依賴

<!-- jwt -->
<dependency>
     <groupId>io.jsonwebtoken</groupId>
     <artifactId>jjwt</artifactId>
     <version>0.9.1</version>
 </dependency>

Jwt配置

common文件夾下新建一個(gè)文件夾utils,然后新建java文件JwtUtil
SpringBoot + Vue前后端分離項(xiàng)目實(shí)戰(zhàn) || 六:Jwt加密整合配置,spring boot,vue.js,后端

寫上下述代碼,注釋已標(biāo)出

package com.ums.common.utils;

import com.alibaba.fastjson2.JSON;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.Date;
import java.util.UUID;

@Component
public class JwtUtil {
    // 有效期
    private static final long JWT_EXPIRE = 30*60*1000L;  //半小時(shí), 單位為毫秒
    // 令牌秘鑰
    private static final String JWT_KEY = "123456";

    // Object data 可放入U(xiǎn)ser對(duì)象,給User中的信息加密后成為token
    public  String createToken(Object data){
        // 當(dāng)前時(shí)間
        long currentTime = System.currentTimeMillis();
        // token過期時(shí)間
        long expTime = currentTime+JWT_EXPIRE;
        // 構(gòu)建jwt
        JwtBuilder builder = Jwts.builder()
                .setId(UUID.randomUUID()+"")
                .setSubject(JSON.toJSONString(data))    // User對(duì)象序列化
                .setIssuer("system")
                .setIssuedAt(new Date(currentTime))
                .signWith(SignatureAlgorithm.HS256, encodeSecret(JWT_KEY))  // 加密
                .setExpiration(new Date(expTime));
        return builder.compact();
    }

    // 加密算法
    private SecretKey encodeSecret(String key){
        byte[] encode = Base64.getEncoder().encode(key.getBytes());
        SecretKeySpec aes = new SecretKeySpec(encode, 0, encode.length, "AES");
        return  aes;
    }

    // token 解密
    public Claims parseToken(String token){
        Claims body = Jwts.parser()
                .setSigningKey(encodeSecret(JWT_KEY))
                .parseClaimsJws(token)
                .getBody();
        return body;
    }

    // token 解密,并返回一個(gè)對(duì)象,可是User對(duì)象
    public <T> T parseToken(String token,Class<T> clazz){
        Claims body = Jwts.parser()
                .setSigningKey(encodeSecret(JWT_KEY))
                .parseClaimsJws(token)
                .getBody();
        return JSON.parseObject(body.getSubject(),clazz);
    }

}

定義Jwt攔截器

XAdminApplication同級(jí)目錄下新建文件夾interceptor,再新建java文件JwtValidateInterceptor
SpringBoot + Vue前后端分離項(xiàng)目實(shí)戰(zhàn) || 六:Jwt加密整合配置,spring boot,vue.js,后端

文件中寫入以下代碼,注釋已給出

package com.ums.interceptor;

import com.alibaba.fastjson2.JSON;
import com.ums.common.utils.JwtUtil;
import com.ums.common.vo.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

// HandlerInterceptor繼承該接口,然后重寫方法
@Component
@Slf4j
public class JwtValidateInterceptor implements HandlerInterceptor {

    @Autowired
    private JwtUtil jwtUtil;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // X-Token 是前端定義的token標(biāo)頭,與前端保持一致
        String token = request.getHeader("X-Token");

        log.debug(request.getRequestURI() +"需要驗(yàn)證:"+ token);     // 后臺(tái)日志記錄
        if (token != null){
            try {
                jwtUtil.parseToken(token);

                // 不要寫System.out.println(); 此為垃圾代碼
                // 加上注解@Slf4j , 用log.debug()來打印
                log.debug(request.getRequestURI() +"驗(yàn)證通過:");
                return true;
            }catch (Exception e) {
                e.printStackTrace();
            }

        }
        log.debug(request.getRequestURI() +"驗(yàn)證失敗,禁止訪問");    // 后臺(tái)日志記錄
        
        // 創(chuàng)建一個(gè)返回對(duì)象,當(dāng)token錯(cuò)誤后反饋給前端
        Result<Object> fail = Result.fail(20003, "token無效,請(qǐng)重新登錄");

        // 驗(yàn)證不成功,給前端返回?cái)?shù)據(jù)
        response.setContentType("application/json;charset=utf-8");  // 定義返回?cái)?shù)據(jù)格式
        response.getWriter().write(JSON.toJSONString(fail));    // 將對(duì)象序列化后以json格式反饋至前端
        return false;   // 攔截當(dāng)前用戶的操作
    }
}

注冊(cè)Jwt攔截器,配置需要驗(yàn)證token的URL

config目錄下新建java文件MyInterceptorConfig
SpringBoot + Vue前后端分離項(xiàng)目實(shí)戰(zhàn) || 六:Jwt加密整合配置,spring boot,vue.js,后端
寫入以下代碼

package com.ums.config;

import com.ums.interceptor.JwtValidateInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MyInterceptorConfig implements WebMvcConfigurer {

    @Autowired
    private JwtValidateInterceptor iwtValidateInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        InterceptorRegistration registration = registry.addInterceptor(iwtValidateInterceptor);
        registration.addPathPatterns("/**")     // 攔截所有URL請(qǐng)求
                .excludePathPatterns(       // 開放下述URL請(qǐng)求
                        "/user/login",
                        "/user/info",
                        "/user/logout"
                );
    }
}

自此,Jwt就算配置完畢
總共新建下述三個(gè)文件
SpringBoot + Vue前后端分離項(xiàng)目實(shí)戰(zhàn) || 六:Jwt加密整合配置,spring boot,vue.js,后端

測(cè)試Jwt

新建一個(gè)測(cè)試類JwtUtilsTest
SpringBoot + Vue前后端分離項(xiàng)目實(shí)戰(zhàn) || 六:Jwt加密整合配置,spring boot,vue.js,后端

@Autowired
private JwtUtil jwtUtil;

@Test
public void testCreateJwt(){
    User user = new User();
    user.setUsername("anthony");
    user.setPhone("14766665555");
    String token = jwtUtil.createToken(user);
    System.out.println(token);
}

運(yùn)行testCreateJwt(),系統(tǒng)會(huì)打印出一個(gè)加密后的字符串,此串會(huì)作為token使用。
SpringBoot + Vue前后端分離項(xiàng)目實(shí)戰(zhàn) || 六:Jwt加密整合配置,spring boot,vue.js,后端

將這個(gè)字符串復(fù)制

新建一個(gè)解密的測(cè)試方法testParseJwt(),下述代碼中復(fù)制你自己的token

 @Test
 public void testParseJwt(){
     String token = "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIwNmRlOGJmOS1kYmM1LTQzNjUtYWRmYi0yYzBjMmVmM2FkOGYiLCJzdWIiOiJ7XCJwaG9uZVwiOlwiMTQ3NjY2NjU1NTVcIixcInVzZXJuYW1lXCI6XCJhbnRob255XCJ9IiwiaXNzIjoic3lzdGVtIiwiaWF0IjoxNjkwMjQ4MjY1LCJleHAiOjE2OTAyNTAwNjV9.iskJNmm6b6rDFs1oxsinrCdFmul0dd9-4_zswD6eGV0";
     Claims claims = jwtUtil.parseToken(token);
     System.out.println(claims);
 }

運(yùn)行后可得到加密的信息
SpringBoot + Vue前后端分離項(xiàng)目實(shí)戰(zhàn) || 六:Jwt加密整合配置,spring boot,vue.js,后端

因?yàn)槲覀兪菍⒁粋€(gè)對(duì)象整體進(jìn)行加密,所以希望在解密的時(shí)候還原為一個(gè)對(duì)象

此時(shí)代碼可這樣寫

 @Test
 public void testParseJw2t(){
     String token = "eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIwNmRlOGJmOS1kYmM1LTQzNjUtYWRmYi0yYzBjMmVmM2FkOGYiLCJzdWIiOiJ7XCJwaG9uZVwiOlwiMTQ3NjY2NjU1NTVcIixcInVzZXJuYW1lXCI6XCJhbnRob255XCJ9IiwiaXNzIjoic3lzdGVtIiwiaWF0IjoxNjkwMjQ4MjY1LCJleHAiOjE2OTAyNTAwNjV9.iskJNmm6b6rDFs1oxsinrCdFmul0dd9-4_zswD6eGV0";
     User user = jwtUtil.parseToken(token,User.class);
     System.out.println(user);
 }

運(yùn)行后得到一個(gè)對(duì)象
SpringBoot + Vue前后端分離項(xiàng)目實(shí)戰(zhàn) || 六:Jwt加密整合配置,spring boot,vue.js,后端

修改登錄等邏輯

現(xiàn)在有了Jwt簽名驗(yàn)證機(jī)制,可將之前的UUID + redis登錄邏輯進(jìn)行修改

打開UserServiceImpl文件
SpringBoot + Vue前后端分離項(xiàng)目實(shí)戰(zhàn) || 六:Jwt加密整合配置,spring boot,vue.js,后端

將之前寫的login(User user)、getUserInfo(String token)、logout(String token)這三段函數(shù)全部重寫
SpringBoot + Vue前后端分離項(xiàng)目實(shí)戰(zhàn) || 六:Jwt加密整合配置,spring boot,vue.js,后端

  1. login(User user)
     @Autowired
     private JwtUtil jwtUtil;
     
     @Override
     public Map<String, Object> login(User user) {
         // 根據(jù)用戶名查詢
         LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(User::getUsername, user.getUsername());
         User loginUser = this.baseMapper.selectOne(wrapper);
    
         // 結(jié)果不為空,并且密碼與數(shù)據(jù)庫(kù)解密后的密碼匹配,生成token,將用戶信息存入redis
         if (loginUser != null &&
                 passwordEncoder.matches(user.getPassword(), loginUser.getPassword())    // 匹配加密密碼
         ) {
             
             loginUser.setPassword(null);    // 設(shè)置密碼為空,密碼沒必要放入
    
             // 創(chuàng)建jwt
             String token = jwtUtil.createToken(loginUser);
    
             // 返回?cái)?shù)據(jù)
             Map<String, Object> data = new HashMap<>();
             data.put("token",token);
             return data;
         }
    
         // 結(jié)果不為空,生成token,前后端分離,前端無法使用session,可以使用token
         return null;
     }
    
  2. getUserInfo(String token)
    @Override
    public Map<String, Object> getUserInfo(String token) {
        // 之前已將對(duì)象進(jìn)行序列化處理存入redis,現(xiàn)在從redis中取出需要反序列化處理
        // Object obj = redisTemplate.opsForValue().get(token);    // 此對(duì)象是map類型,稍后需要序列化為Json字符串
        // User loginUser = JSON.parseObject(JSON.toJSONString(obj), User.class);
    
    
        User loginUser = null;
    
        try {
            // 解析Token
            loginUser = jwtUtil.parseToken(token, User.class);
        }catch (Exception e) {
            e.printStackTrace();
        }
    
        if (loginUser != null) {
            Map<String,Object> data = new HashMap<>();
            data.put("name",loginUser.getUsername());
            data.put("avatar",loginUser.getAvatar());
    
            // 先在xml里寫SQL語(yǔ)句 id=getRoleNameByUserId,然后去UserMapper里實(shí)現(xiàn)接口
            List<String> roleList = this.baseMapper.getRoleNameByUserId(loginUser.getId());
            data.put("roles",roleList);
            return data;
        }
        return null;
    }
    
  3. logout(String token) , 注釋以前的代碼,可啥也不用寫!
    @Override
    public void logout(String token) {
        // redisTemplate.delete(token);    // 從redis中刪除token
    }
    

自此完畢!文章來源地址http://www.zghlxwxcb.cn/news/detail-616016.html

到了這里,關(guān)于SpringBoot + Vue前后端分離項(xiàng)目實(shí)戰(zhàn) || 六:Jwt加密整合配置的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包