Vue+Vuex實現自動登錄 升級版


Vue+Vuex實現自動登錄 升級版

之前實現的版本在這里:Vue+Vuex實現自動登錄

      在之前實現的版本中,如果你進行測試,可以看到在瀏覽器的local Storage中,確實里面有了我們加入的Authorization,而且如果沒有登錄的話,直接訪問主頁會進入登錄頁面。但其實有好幾個問題並沒有解決:
      一、我們所加的Authorzation其實並不是從服務器傳過來的,而是自己的測試:只要服務器傳過來了200的響應狀態碼,我們就自己加上固定的Authorization
      二、我們重新進入的時候,判斷條件是只要有Authorization就可以直接進入了,但其實應該提交給服務器判斷這個Authorization是否在數據庫中,才可以。

     基於以上兩點,我們對代碼進行修改:
     首先就是,我們獲取的token應該是從服務器獲取的,而不是自己給定,因此直接在服務器上接收到信息后修改:

@RequestMapping(value = "/login",method = RequestMethod.POST)
    public RespBean login(
            @RequestBody UserLogin userLogin,
            Model model
    ){
        if (userService.check(userLogin)){
            String token = UUID.randomUUID().toString();
//            System.out.println(token);
            userService.autoLog(userLogin,token);
            return new RespBean("success","登錄成功",token);

        }else{
            return new RespBean("fail","登錄失敗");
        }
    }

這里使用uuid直接生成隨機的token,為了用respBean傳遞回去數據,因此傳遞回去的對象除了狀態信息和消息之外,還需要多加一個token:
RespBean對象代碼為:

    public class RespBean {
    private String status;
    private String msg;
    private String token = null;
}

各種方法自己加上就好了。
     如果仔細的話,會發現我們傳進來的參數好像跟上一次的不一樣了,上一次傳遞了兩個用@RequestParam修飾的賬號密碼的String類型的對象,而這一次直接傳遞了一個UserLogin的對象,這是因為我覺得如果要接收表單等信息的話,每一個都使用這樣的一個個參數會顯得接收參數很多,而且如果要修改接收的數值的話,可能需要很多地方都要修改,復用性太差了。
     第二個原因是我們的Controller層應該只是最大限度的邏輯表示,而具體怎么添加用戶、怎么鑒別用戶是否登錄等信息,完完全全應該交給下層的Service層呀Mapper層呀去做,但如果接收的是這樣的password、username等數值的話,調用下一層的時候,我們還需要把這些數值直接放入,否則就要在Controller層對數據進行操作,這就破壞層次結構了。
     所以,為了解決這個問題,我們可以把所有表單中需要用到的數據單獨封裝成一個對象,這個對象就專門用來接收web的數據以及在各個層之間流轉:

@Data
public class UserLogin {
    private String username;
    private String password;
}
```把,
     這里的@Data注解就是lombok的注解,可以讓我們不用再去創建get、set等方法了。這樣創建完對象以后,我們的登錄操作就可以直接將這樣的對象拿來使用了。
     但是,如果你是跟着做下來的,就會遇到跟我一樣的問題:登錄的時候會報錯:
####Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unrecognized token 'username': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false'); nested exception is com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'username': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false')
     大概的意思就是說,我們接受的跟發出的不大一樣,對應不上,而這樣的原因是:我們當時為了使用get和@RequestParam方法,在api.js中,把獲取到的json數據格式,變成了json字符串的格式了,所以就不能使用@RequestBody這樣一個接收json對象的方法來接收了。
因此上一個程序中的api.js改為:
```javascript
export const postRequest = (url, params) => {
  return axios({
    method: 'post',
    url: `${base}${url}`,
    data: params,

    // transformRequest: [function (data) {
    //   // Do whatever you want to transform the data
    //   let ret = ''
    //   for (let it in data) {
    //     ret += encodeURIComponent(it) + '=' + encodeURIComponent(data[it]) + '&'
    //   }
    //   return ret
    // }],
    headers: {
      'Content-Type': 'application/json;charset=UTF-8'
    }
  });
}

詳細的可以看一下這個文章@RequestBody和@RequestParam的區別

而第二點,關於如何實現鑒別token,就是在路由之前的那個方法上,加上傳遞給服務器以及接收相應信息進行操作:

router.beforeEach((to,from,next)=>{
  if(to.path ==='/login'){
    next();
  }else {
    let token = localStorage.getItem('Authorization');

    if(token ===null || token ===''){
      next('/login');
    }else {
      getRequest('/autoLog',{
          token:token
      }).then(resp=>{
        if(resp.status == 200){
           var json = resp.data;
            if(json.status=='success'){
              next();
            }else{
              // next('/login');
            }
        }else{
          alert('請求失敗', '失敗!');
        }
      })
    }
  }
});

服務器的處理也就很簡單了,跟上面登錄其實是差不多的,就不再列舉出來了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM