vue前後端分離,做普通的登錄攔截(未登錄:返回一個自定義Exception;放開白名單:通過給方法加上自定義註解,在攔截器中查看過來的方法是否有該註解,有則放開攔截)

vue前後端分離,做普通的登錄攔截(未登錄:返回一個自定義Exception;放開白名單:通過給方法加上自定義註解,在攔截器中查看過來的方法是否有該註解,有則放開攔截)

1.寫一個登錄頁面

<template>
<div>
  <el-form  :model="user"  :rules="rules" ref="ruleForm" label-width="80px"  class="demo-ruleForm" style="margin-left: 35%;margin-top: 5%">
    <el-form-item label="賬戶" prop="name">
      <el-input v-model="user.name" style="width: 300px"></el-input>
    </el-form-item>
    <el-form-item label="密碼" prop="password">
      <el-input v-model="user.password" style="width: 300px"></el-input>
    </el-form-item>

    <el-form-item>
      <el-button type="primary" @click="onSubmit" style="margin-left: 50px;">登錄</el-button>
      <!--如果在index.js中,不配置  mode:'history',去掉訪問請求中的"#",就需要在前邊加一個#-->
      <!--<el-link href="#/register" type="primary"  style="margin-left: 30px;">註冊</el-link>-->
      <el-link href="/regiterUser" type="primary"  style="margin-left: 30px;">註冊</el-link>

    </el-form-item>
  </el-form>

</div>
</template>

<script>
  export default {
    name: 'Loogin',
    data(){
      //驗證用戶名不能爲空
      //checkName與rule中定義的必須保持一致1
      var checkName = (rule, value, callback) => {
        //alert(this.user.name)
        if (value === '') {
          callback(new Error('請輸入賬號'));
        }
      };
      var validatePass = (rule, value, callback) => {
        if (value === '') {
          callback(new Error('請輸入密碼'));
        }
      };
      return {
        user: {
          password: '',
          name: ''
        },
        /*rules與form中的:rules="rules"保持一致*/
        rules: {
          password: [
            { validator: validatePass, trigger: 'blur' }
          ],
          name: [
            { validator: checkName, trigger: 'blur' }
          ]
        }
      };
    },
    methods:{
      onSubmit(){
        var self = this;
        this.$axios.post('http://localhost:8089/user/loginUser.do',this.$qs.stringify(this.user)).then(function (response) {
          console.log(response)
          if (response.data.code===1000){
            //跳轉到登錄頁面
            self.$router.push("/indexPage")
          }else{
            alert(response.data.data);
            //  self.$router.push("/")
          }
        })
      }
    }
  }
</script>

<style scoped>

</style>

2.寫一個註冊頁面,表單驗證【因爲涉及到MD5加鹽加密,先註冊幾條數據】

<template>
  <div>
    <el-form :model="user" status-icon :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm" style="margin-left: 35%;margin-top: 5%">
      <el-form-item label="賬號" prop="name">
        <el-input v-model.number="user.name"  style="width: 300px"></el-input>
      </el-form-item>
      <el-form-item label="密碼" prop="password">
        <el-input type="password" v-model="user.password" autocomplete="off"  style="width: 300px"></el-input>
      </el-form-item>
      <el-form-item label="確認密碼" prop="checkPass">
        <el-input type="password" v-model="user.checkPass" autocomplete="off"  style="width: 300px"></el-input>
      </el-form-item>

      <el-form-item>
        <el-button type="primary" @click="submitForm('ruleForm')" style="margin-left: 50px;">提交</el-button>
        <el-button @click="resetForm('ruleForm')" style="margin-left: 30px;">重置</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<script>
  export default {
    name: 'regiterUser',
    data() {
      var checkName = (rule, value, callback) => {
        if (value === '') {
          callback(new Error('請輸入賬號'));
        }else{
          //查詢賬號是否存在
          this.$axios.post('http://localhost:8089/user/checkUserByName.do',this.$qs.stringify({"name":this.user.name})).then(function (response) {
            if (response.data.code===1000){
              callback();
            }
            else{
              callback(new Error('賬號已存在'));
            }
          })
        }
      };
      var validatePass = (rule, value, callback) => {
        if (value === '') {
          callback(new Error('請輸入密碼'));
        } else {
          if (this.user.checkPass !== '') {
            this.$refs.ruleForm.validateField('checkPass');
          }
          callback();
        }
      };
      var validatePass2 = (rule, value, callback) => {
        if (value === '') {
          callback(new Error('請再次輸入密碼'));
        } else if (value !== this.user.password) {
          callback(new Error('兩次輸入密碼不一致!'));
        } else {
          callback();
        }
      };
      return {
        user: {
          password: '',
          checkPass: '',
          name: ''
        },
        rules: {
          password: [
            { validator: validatePass, trigger: 'blur' }
          ],
          checkPass: [
            { validator: validatePass2, trigger: 'blur' }
          ],
          name: [
            { validator: checkName, trigger: 'blur' }
          ]
        }
      };
    },
    methods: {
      submitForm(formName) {
        this.$refs[formName].validate((valid) => {
          if (valid) {
            alert('submit!');
            var self = this;
            this.$axios.post('http://localhost:8089/user/registerUser.do',this.$qs.stringify(this.user)).then(function (response) {
              if (response.data.code===1000){
                //跳轉到登錄頁面
                self.$router.push("/")
              }
            })

          } else {
            console.log('error submit!!');
            return false;
          }
        });
      },
      resetForm(formName) {
        this.$refs[formName].resetFields();
      }
    }
  }
</script>

<style scoped>

</style>

3.正式開始登錄攔截代碼

1)在spring-mvc-controller.xml配置攔截器

 <!--配置攔截器-->
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
                 <!-- 按照以往方式,在這裏配置不需要攔截的,這裏換通過註解來查詢不需要攔截的方法,然後放開,此處就不需要了-->
            <!-- 代表哪些方法不用攔截 (可以配置多個)-->
           <!-- <mvc:exclude-mapping path="/user/checkUserByName.do"/>
            <mvc:exclude-mapping path="/user/registerUser.do"/>
            <mvc:exclude-mapping path="/user/loginUser.do"/>-->
            <bean class="com.fh.intercetpor.LoginInterceptor"/>
        </mvc:interceptor>

    </mvc:interceptors>

2)自定義一個註解類【如果不攔截的方法,就被該自定義的註解修飾,在interceptor中判斷,如果訪問的方法有該註解,則放開攔截】

@Documented //它的作用是能夠將註解中的元素包含到 Javadoc 中去
@Target(ElementType.METHOD) //表示我們的註解作用的範圍就比較具體了,可以是類,方法,方法參數變量
@Retention(RetentionPolicy.RUNTIME)//它表示註解存在階段是保留在源碼(編譯期),註解會在class字節碼文件中存在,在運行時可以通過反射獲取到
public @interface Ignore {


}

例如:

/**
     * 通過name查詢用戶是否存在
     * @param name
     * @return
     */
    @Ignore
    @RequestMapping("checkUserByName")
    public ResponseServer checkUserByName(String name){

        return userService.checkUserByName(name);
    }


    /**
     * 註冊用戶
     * @param user
     * @return
     */ 
    @Ignore
    @RequestMapping("registerUser")
    public ResponseServer registerUser(User user){

        return userService.registerUser(user);

    }

3)寫一個異常類,當用戶,沒有登錄時,就throw自定義的異常

/**
 * 寫一個異常類,運行時異常,也可以是其他的異常,根據情況需要
 */
public class MyException extends RuntimeException {
}

寫一個全局的異常類

因爲是controller的註解,所以需要在controller的配置文件中,conpent-scan中配置對該異常的文件掃描

/**
 * 配置一個全局的異常
 * 把需要配置的異常在這裏進行配置,當拋異常時候,返回前臺一個error,前臺就可以根據這個返回的code進行判斷
 * @RestController 寫上以後,下邊的方法就不需要寫ReponseBody
 *
 * 要使註解生效,在spring-mvc-controller.xml文件需要配置
 */
@RestControllerAdvice
public class ClobleHandlerException {


    /**
     * 自定義的異常
     * @param e
     * @return
     */
    @ExceptionHandler(MyException.class)
    public ResponseServer myExceptionHandler(MyException e){
        e.printStackTrace();
        return  ResponseServer.errorMethod();
    }


    /**
     * 拋所有的異常
     * @param e
     * @return
     */
    @ExceptionHandler(Exception.class)
    public ResponseServer exceptionHandler(Exception e){
        e.printStackTrace();
        return ResponseServer.errorMethod();
    }


}
 <!--Exception中,有controller的註解,使其生效-->
    <context:component-scan base-package="com.fh.exception"/>

4)寫攔截器

/**
 * 登錄攔截,利用ignore來做的,不需要在spring-mvc.xml中配置
 */
public class LoginInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        //1.在這裏設置全局的跨域問題,所以在controller層的跨域註解也可以不用寫了
        //處理跨域問題
        response.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN,"http://localhost:8081");
        //處理客戶端傳過來的自定義頭信息【自定義:從前臺地址欄查看,傳過來的信息是何種信息,然後添加上,纔可以放開攔截,否則就會攔截】
        response.addHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS,"x-auth,content-type,mtoken");
        //處理客戶端發過來的put delete【自定義的,從前臺發送請求的路徑中查看,需要添加何種請求,然後添加上,纔可以放開攔截,否則就會攔截】
        response.addHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS,"PUT,POST,DELETE,GET");
        //跨域,如果登錄攔截時候,訪問不到後臺數據,瀏覽器就會報:No 'Access-Control-Allow-Origin' header is present on the requested ,加上這個就不會報了
        response.addHeader("Access-Control-Allow-Credentials","true");

        //2.判斷訪問的請求是否是:註解@Ignore修飾的方法
        //獲取方法
        HandlerMethod handlerMethod = (HandlerMethod)handler;
        Method method = handlerMethod.getMethod();
        //判斷該方法是否有@Ignore註解
        if(method.isAnnotationPresent(Ignore.class)){
            //如果有,放開
            return true;
        }


        //獲取session,查看是否有用戶登錄
        User user = (User) request.getSession().getAttribute(Const.LOGIN_SESSION_USER);


        if(user == null){
            //證明沒有有用戶登錄,則拋自定義的異常
            throw new MyException();
        }
        return true;
    }
}

vue頁面配置:
main.js

// 把coookie發送到服務器
axios.defaults.withCredentials = true
// 定義一個請求攔截器
axios.interceptors.request.use(function (config) {
  console.log(config)
  return config
})
// 定義一個相應攔截器
axios.interceptors.response.use(function (config) {
  console.log(config)
  // 錯誤的code=2000,如果=2000,則證明沒有登錄,跳到登錄頁面
  if (config.data.code === 2000) {
    location.href = '/'
  }
  return config
})

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章