场景:
自定义一个过滤器,过滤验证码是否填写(集成SpringSecurity)
前端:
<!--登录页面--> <template> <div class="login-container"> <el-form :model="loginForm" :rules="rules2" status-icon ref="loginForm" label-position="left" label-width="0px" class="demo-ruleForm login-page"> <h3 class="title">用户登录</h3> <el-form-item prop="username"> <el-input type="text" v-model="loginForm.username" auto-complete="off" placeholder="用户名" ></el-input> </el-form-item> <el-form-item prop="password"> <el-input type="password" v-model="loginForm.password" auto-complete="off" placeholder="密码" ></el-input> </el-form-item> <el-form-item prop="code"> <el-input v-model="loginForm.code" auto-complete="off" placeholder="验证码" style="width: 63%" @keyup.enter.native="handleLogin" > <svg-icon slot="prefix" icon-class="validCode" class="el-input__icon input-icon" name = "yzm"/> </el-input> <div class="login-code"> <img :src="codeUrl" @click="getCode" class="login-code-img"/> </div> </el-form-item> <el-checkbox v-model="loginForm.rememberMe" style="margin:0px 0px 25px 0px;">记住密码</el-checkbox> <el-form-item style="width:100%;"> <el-button :loading="loading" size="medium" type="primary" style="width:100%;" @click.native.prevent="handleLogin" > <span v-if="!loading">登 录</span> <span v-else>登 录 中...</span> </el-button> <div style="float: right;"> <router-link class="link-type" :to="'/register'">立即注册</router-link> </div> </el-form-item> </el-form> </div> </template> <script> import ElPager from "element-ui/packages/pagination/src/pager"; import { encrypt, decrypt } from '../utils/jsencrypt' import Cookies from "js-cookie"; export default { components: {ElPager}, data(){ return { codeUrl: "", loginForm: { username: 'admin', password: '123', rememberMe: false, code: "" }, rules2: { username: [{required: true, message: '请输入用户名', trigger: 'blur'}], password: [{required: true, message: '请输入密码', trigger: 'blur'}], code: [{ required: true, message: "请输入验证码", trigger: "change" }] }, loading: false, redirect: undefined } }, //监听 watch: { $route: { handler: function(route) { this.redirect = route.query && route.query.redirect; }, immediate: true } }, created() { this.getCode(); this.getCookie(); }, methods: { //获取验证码 getCode(){ this.$axios.get("http://localhost:8090/vercode").then(res=>{ this.codeUrl = "data:image/gif;base64," + res.data.img; }).catch(error=>{ console.log(error) }) }, //Cookie加密 getCookie() { const username = Cookies.get("username"); const password = Cookies.get("password"); const rememberMe = Cookies.get('rememberMe'); this.loginForm = { username: username === undefined ? this.loginForm.username : username, password: password === undefined ? this.loginForm.password : decrypt(password), rememberMe: rememberMe === undefined ? false : Boolean(rememberMe) }; }, //点击登录 handleLogin(){ //表单验证 this.$refs.loginForm.validate(valid => { if(valid) { this.loading = true; //如果开启了记住我功能,Cookie对密码加密 if (this.loginForm.rememberMe) { Cookies.set("username", this.loginForm.username, { expires: 30 }); Cookies.set("password", encrypt(this.loginForm.password), { expires: 30 }); Cookies.set('rememberMe', this.loginForm.rememberMe, { expires: 30 }); } else { Cookies.remove("username"); Cookies.remove("password"); Cookies.remove('rememberMe'); } this.$axios.post("http://localhost:8090/doLogin", this.loginForm).then(res=>{ // 路由跳转指定页面 this.$router.push({ path: this.redirect || "/" }).catch(()=>{}); //登录成功 this.$message({ message: '恭喜你,登录成功', type: 'success' }); }).catch(error=>{ this.loading = false; this.getCode(); this.$message.error(error.data); }) } }); }, } }; </script> <style scoped> .login-container { width: 100%; height: 100%; } .login-page { -webkit-border-radius: 5px; border-radius: 5px; margin: 180px auto; width: 350px; padding: 35px 35px 15px; background: #fff; border: 1px solid #eaeaea; box-shadow: 0 0 25px #cac6c6; } label.el-checkbox.rememberme { margin: 0px 0px 15px; text-align: left; } </style>
后端:
package com.aoshen.common; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.aoshen.common.redis.RedisCache; import com.aoshen.common.utils.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.AuthenticationServiceException; import org.springframework.stereotype.Component; import org.springframework.web.filter.GenericFilterBean; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; /** * @author aoshen * DATE 2021/12/6 15:22 * 自定义过滤器:过滤验证码是否填写 */ @Component public class VerifyCodeFilter extends GenericFilterBean { @Autowired private RedisCache redisCache; private String defaultFilterProcessUrl = "/doLogin"; //过滤访问的接口 @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; if ("POST".equalsIgnoreCase(request.getMethod()) && defaultFilterProcessUrl.equals(request.getServletPath())) { // 从request中读取POST请求参数 ServletInputStream inputStream = request.getInputStream(); InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8); BufferedReader bfReader = new BufferedReader(reader); StringBuilder sb = new StringBuilder(); String line; while ((line = bfReader.readLine()) != null){ sb.append(line); } String str = sb.toString(); JSONObject jsonObject = JSON.parseObject(str); String requestCaptcha = jsonObject.getString("code"); //从redis中拿取 String genCaptcha = redisCache.getCacheObject("vercode"); if (StringUtils.isEmpty(requestCaptcha)) { throw new AuthenticationServiceException("验证码不能为空!"); } if (!genCaptcha.toLowerCase().equals(requestCaptcha.toLowerCase())) { throw new AuthenticationServiceException("验证码错误!"); } } chain.doFilter(request, response); } }