基于springboot-Vue的登录实现

目录

路由拦截器

登录界面进行请求访问后端

后端通过通过拦截器放行

登录真正实现

axios前置拦截器

axios后置拦截器


本文章是基于Vue框架下的登录实现,运用了redis技术和不局限与游览器的loaclstora来存储登录信息

路由拦截器

首先运用路由拦截器,限制其他资源的访问

router.beforeEach((to, from, next) => {
  //NProgress.start();
  if (to.path == '/login') {
    localStorage.removeItem('loginInfo');
  }
  let user = JSON.parse(localStorage.getItem('loginInfo'));
  if (!user && to.path != '/login' && to.path != '/shopregist') {
    next({ path: '/login' })
  } else {
    next()
  }
})

 登录界面进行请求访问后端

<template>
  <el-form :model="ruleForm2" :rules="rules2" ref="ruleForm2" label-position="left" label-width="0px" class="demo-ruleForm login-container">
    <h3 class="title">系统登录</h3>
    <el-form-item prop="account">
      <el-input type="text" v-model="ruleForm2.username" auto-complete="off" placeholder="账号"></el-input>
    </el-form-item>
    <el-form-item prop="checkPass">
      <el-input type="password" v-model="ruleForm2.password" auto-complete="off" placeholder="密码"></el-input>
    </el-form-item>
    <el-checkbox v-model="checked" checked class="remember">记住密码</el-checkbox>
    <el-form-item style="width:100%;">
      <el-button type="primary" style="width:47%;" @click.native.prevent="login" :loading="logining">登录</el-button>
      <el-button type="primary" style="width:47%;" @click.native.prevent="shopregist" :loading="logining">商家入驻</el-button>
      <!--<el-button @click.native.prevent="handleReset2">重置</el-button>-->
    </el-form-item>
  </el-form>
</template>

<script>
  import { requestLogin } from '../api/api';
  //import NProgress from 'nprogress'
  export default {
    data() {
      return {
        logining: false,
        ruleForm2: {
          username: '',
          password: '',
          loginType:null,
        },
        rules2: {
          username: [
            { required: true, message: '请输入账号', trigger: 'blur' },
            //{ validator: validaePass }
          ],
          password: [
            { required: true, message: '请输入密码', trigger: 'blur' },
            //{ validator: validaePass2 }
          ]
        },
        checked: true
      };
    },
    methods: {
      shopregist(){
        this.$router.push({ path: '/shopregist' });
      },
      handleReset2() {
        this.$refs.ruleForm2.resetFields();
      },
      login() {
        this.$refs.ruleForm2.validate((valid) => {
          if (valid) {
            this.logining = true;
            this.ruleForm2.loginType=0;
            this.$http.post("/logininfo/account",this.ruleForm2)
                .then(result=>{
                  this.logining = false;
                  result = result.data;
                  if(result.success)
                  {
                    //提示
                    this.$message({
                      message: "登录成功!",
                      type: 'success'
                    });
                    //把token和loginInfo存放到localStorage
                    let {token,loginInfo} = result.data;
                    localStorage.setItem("token",token);
                    //把对象转换为json字符串存放
                    localStorage.setItem("loginInfo",JSON.stringify(loginInfo));
                    //跳转主页
                    this.$router.push({ path: '/echarts' });
                  }else{
                    //提示
                    this.$message({
                      message: result.message,
                      type: 'error'
                    });
                  }
                })
                .catch(result=>{
                  this.logining = false;
                  this.$message({
                    message: "系统错误!",
                    type: 'error'
                  });
                })
          } else {
            console.log('error submit!!');
            return false;
          }
        });
      }
    }
  }

</script>

后端通过通过拦截器放行

定义后端拦截器

package com.ronghua.user.interceptor;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.concurrent.TimeUnit;

/**
 * 登录拦截器
 *
 * @author wangling
 * @date 2022/09/17
 */
@Component
public class LoginInterceptor implements HandlerInterceptor {
    @Autowired
    private RedisTemplate redisTemplate;
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
          //如果对用户有权限拦截,先对用户进行权限的判断,有权限在进行资源的访问 @TODO //运用springsecurity技术
        String token = request.getHeader("token");//访问其他资源时,拿到请求中的token
        if (!StringUtils.isEmpty(token)){//当token不为空的时候
            Object obj = redisTemplate.opsForValue().get(token);//从redis中拿到token的值
            if (obj!=null){//redis中拿到了token的值
                /*因为前端给所有请求都加了token,也就是操作的时候都有token进来,所有每次进来都再次设置个30分钟,防止它在操作的时候突然过期了,结果访问下一个请求就又要重新登录*/
                redisTemplate.opsForValue().set(token,obj,30, TimeUnit.MINUTES);
                return true;
            }
        }
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/json; charset=UTF-8");
        PrintWriter writer = response.getWriter();
        // 在外面写好在拷贝进去
        writer.write("{\"success\":false,\"message\":\"noLogin\"}");
        writer.close();
        return false;
    }
}

在启动类里面配置拦截器,通过实现WebMvcConfigurer添加拦截器

package com.ronghua;

import com.ronghua.user.interceptor.LoginInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

//入口类测试
@SpringBootApplication
@MapperScan("com.ronghua.*.mapper")
//开启缓存注解
@EnableCaching
public class CarAppStart implements WebMvcConfigurer {
    @Autowired
    private LoginInterceptor loginInterceptor;
    public static void main(String[] args) {
        SpringApplication.run(CarAppStart.class, args);
    }
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor)
                .addPathPatterns("/**") //拦截地址 一级二级都拦截
                .excludePathPatterns("/logininfo/**")//放行登录
                .excludePathPatterns("/user/register/**")//放行注册
                .excludePathPatterns("/verifycode/**")//验证码
                .excludePathPatterns("/fastDfs");//分布式文件服务器
    }
}

登录真正实现

controller层---这里的Ajaxresult是自己编写的一个响应类

  @PostMapping("/account")
    public AjaxResult logingAccount(@RequestBody LoginDto loginDto){
        try {
            return logininfoService.logingAccount(loginDto);
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.me().setSuccess(false).setMessage("登录失败!"+e.getMessage());
        }
    }

service层

 public AjaxResult logingAccount(LoginDto loginDto) {
        String username = loginDto.getUsername();
        String password = loginDto.getPassword();
        Integer loginType = loginDto.getLoginType();
        //1 校验
        // 1.1 null判断
        if (StringUtils.isEmpty(username)||StringUtils.isEmpty(password)||loginType==null)
            return AjaxResult.me().setSuccess(false).setMessage("输入的信息不能为空");
        // 1.2 判断用户是否存在 Username--username,phone,email
        Logininfo logininfo=logininfoMapper.loadByName(loginDto);//数据库中查询此用户是否存在,这里可以直接通过用户名来查
        if (logininfo==null)
            return AjaxResult.me().setSuccess(false).setMessage("该用户不存在");
        // 1.3 判断用户状态是否ok
        if (logininfo.getDisable()==-1)
            return AjaxResult.me().setSuccess(false).setMessage("该用户已经被冻结,请联系管理员");
        //比对密码
        String salt = logininfo.getSalt();//这是加密使用的盐值
        String saltpassword = MD5Utils.encrypByMd5(password + salt);//通过MD5和盐值加密来对数据库的密码进行比对
        if (!saltpassword.equals(logininfo.getPassword()))
            return AjaxResult.me().setSuccess(false).setMessage("输入的密码不正确");
        //3 记录logininfo到redis,key是token
        String token = UUID.randomUUID().toString();//通过uuid创建一个token,这里的token是用来做axios的前置拦截用的
        redisTemplate.opsForValue().set(token, logininfo, 30, TimeUnit.MINUTES);
        //4 返回AjaxResult,如果登录成功,还需要返回token和loginInfo
        Map<String,Object> map=new HashMap<>();
        map.put("token", token);
        //为了安全起见,把前台不会用到敏感信息salt和password去空
        logininfo.setSalt(null);
        logininfo.setPassword(null);
        map.put("loginInfo", logininfo);
        return AjaxResult.me().setData(map);
    }

axios前置拦截器

为了安全起见,在前端发请求的时候加一个前置拦截器,访问其他资源请求时通过token来成功访问,我使用的是axios来发请求

import axios from 'axios'
axios.defaults.baseURL='http://localhost:80'
//==========axios的前置拦截=========
axios.interceptors.request.use(config=>{
  let token = localStorage.getItem("token")
  if(token){
    config.headers["token"] = token;
  }
  return config;
},error => {
  Promise.reject(error)
})

axios后置拦截器

如果localstorage里面没有token,也就是别人跳过密码攻击网站,localstorage里面是没有token就会通过后端的发送的失败信息,在通过前端的后置拦截器跳转的登录界面,并删除localstorage的信息。(后端拦截器已经配置了有token请求的访问放行)

axios.interceptors.response.use(config=>{
  console.log("========")
  let data = config.data;
  if(!data.success && "noLogin"===data.message)
  {
    localStorage.removeItem("token");
    localStorage.removeItem("loginInfo");
    router.push({ path: '/login' });
  }
  console.log("========")
  return config;
},error => {
  Promise.reject(error)
})

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值