登录的前后端实现

246 阅读3分钟

登录逻辑,前后端完整实现:

1,用户名,密码验证成功后,后端签发token返回给前端

2,前端把token保存到本地存储

补充:

http是无状态的,意思是说你这次访问了服务器,关闭网页,再次访问服务器,服务器是没有意识到又是你来访问的

image.png

    login() {
      this.$api.users
        .login(this.user)
        .then(({ data }) => {
          const { accessToken } = data
          localStorage.setItem('token', accessToken)
          this.$router.push('/products/create')
        })
        .catch((err) => {
          this.$message.error(err.response.data.message)
        })
    },

注:

如果token不保存,则如果知道其他非登录页的路由地址可以直接跳过登录页,登录页就没有起到真正的作用。

仅仅判断本地有没有token不行 因为可以在浏览器调试模式下自己填入token,所以在请求时需要带上token 信息发送给后端验证

3,每次请求前,通过axios请求拦截器,统一发送token

请求拦截器 axios intercept config就是axios.create({})括号里的对象

request.interceptors.request.use(
  (config) => {
    const token = localStorage.getItem('token')
    if (token) config.headers.Authorization = `Bearer ${token}`;
    return config
  },
  (error) => Promise.reject(error),
)

4,通过Vue导航守卫,和axios响应拦截器,统一保护页面

导航守卫 全局前置守卫 判断本地是否有token

router.beforeEach((to, from, next) => {
  const token = localStorage.getItem('token')
  if (to.name !== 'Login' && !token) next({ name: 'Login' })
  else next()
})

响应拦截器

是在请求拿到数据之后,在.then .catch之前 。 用于处理后端检验token的结果,如果状态码为401 则跳回登录页 弹出错误信息message

需要注意的是 在js中使用elementui的message组件不能写成this.$message

request.interceptors.response.use(
  (response) => response,
  ({ response }) => {
    const { status, data } = response
    const { message } = data
    Message.error(message)
    if (status === 401) router.push({ name: 'Login' })
    return Promise.reject(error)
  },
)

http请求码 200 201 成功 204 无内容 通常用于删除接口

301 永久重定向 用于域名网址需要更改时,老的域名已经被百度收录,所以更改需要重定向并通知百度 304 临时重定向

400 接口传参 请求参数的格式错误 接口传参最少有四个地方可以: 路径参数 查询参数 请求头参数 请求体参数

image.png

401 后端校验token失败,前端直接跳到登录页,代表未登录 获得token过期了或者没传 或者传错了

403 代表无权限,登录了权限过低,某些接口不能调用

404 请求资源找不到 请求地址写错了,需要检查请求路径是否敲错了或者是否请求方法错误 get写成了post

500 通常是后端代码写错了 502 服务器配置错误 503 服务器超载了

翻译为请求报文为:

image.png

登录页面的优化:

优化一:用户名和密码输入之后敲回车 可以请求接口

@keyup.enter.native = ''

native是绑定keyup事件在组件的最外层的div上 组件本身没有keyup事件

优化二:用户名和密码都填完之后button才能点击,只填一个或者不填是不能点击的

 <el-button
          type="primary"
          @click="login"
          :disabled="!canSubmit"
        >
          登录
 </el-button>
 
   computed: {
    canSubmit() {
      const { username, password } = this.user
      return Boolean(username && password)
    },
  },

优化三:输入框小到一定程度不能再小了,不影响输入

优化四:变小的过程中 表单不那么居中了,是因为每一个form-item都有margin-bottom 需要设置最后一个form-item的margin-bottom为0

.el-form-item:last-child {
  margin-bottom: 0;
}

其他:

本地存储是和域名相关的 保证origin域一样都能拿到 不可能京东的token会拿到qq的token jd.com token = 111 qq.com token = 222

哪些路由需要登录?

可以在route中添加meta属性 里面可以随便保存信息 定义的只是一个标记

meta: { authRequired: true },