SpringBoot前后端分离登陆验证码实现以及不显示问题

最近在做一个项目,就是先完成登陆的一个验证码简单验证,一开始使用了js前端完成,但是项目不允许,我去!很纳闷前端生成验证码,进行验证也能完成功能呀,并且很简单,只要一个插件几行代码的事情,非要后端使用session验证,尴尬了,显示用前端完成的代码先上。

纯前端完成验证码的生成和获取:





不让使用前端代码,那就只能使用后端生成喽,从网上借鉴了大神,完成了前后端分离session存储的验证码的生成以及获取和验证

1、先上html和js文件








    
    


    后台登录

     
    

    
    
    
    




    

华佗故里,药材之乡

点击更换验证码

2、以下是生成验证码工具类:

package com.qfant.config;



import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;

/**
 * 验证码生成类
 * 

* @author admin * */ public class RandomValidateCode { public static final String RANDOMCODEKEY = "RANDOMVALIDATECODEKEY";//放到session中的key      //private String randString = "0123456789";//随机产生只有数字的字符串 private String private String randString = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";//随机产生只有字母的字符串 //private String randString = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";//随机产生数字与字母组合的字符串   private int width = 95;// 图片宽   private int height = 25;// 图片高   private int lineSize = 40;// 干扰线数量   private int stringNum = 4;// 随机产生字符数量   private Random random = new Random(); /*      * 获得字体      */ private Font getFont() { return new Font("Fixedsys", Font.CENTER_BASELINE, 18); } /*      * 获得颜色      */ private Color getRandColor(int fc, int bc) { if (fc > 255) fc = 255; if (bc > 255) bc = 255; int r = fc + random.nextInt(bc - fc - 16); int g = fc + random.nextInt(bc - fc - 14); int b = fc + random.nextInt(bc - fc - 18); return new Color(r, g, b); } /** *      * 生成随机图片 *      */ public void getRandcode(HttpServletRequest request, HttpServletResponse response) { HttpSession session = request.getSession(); // BufferedImage类是具有缓冲区的Image类,Image类是用于描述图像信息的类   BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR); Graphics g = image.getGraphics();// 产生Image对象的Graphics对象,改对象可以在图像上进行各种绘制操作   g.fillRect(0, 0, width, height); g.setFont(new Font("Times New Roman", Font.ROMAN_BASELINE, 18)); g.setColor(getRandColor(110, 133)); // 绘制干扰线   for (int i = 0; i <= lineSize; i++) { drowLine(g); } // 绘制随机字符   String randomString = ""; for (int i = 1; i <= stringNum; i++) { randomString = drowString(g, randomString, i); } //将生成的随机字符串保存到session中,而jsp界面通过session.getAttribute("RANDOMCODEKEY"),   //获得生成的验证码,然后跟用户输入的进行比较   session.removeAttribute(RANDOMCODEKEY); session.setAttribute(RANDOMCODEKEY, randomString); g.dispose(); try { // 将内存中的图片通过流动形式输出到客户端   ImageIO.write(image, "JPEG", response.getOutputStream()); } catch (Exception e) { e.printStackTrace(); } } /*      * 绘制字符串      */ private String drowString(Graphics g, String randomString, int i) { g.setFont(getFont()); g.setColor(new Color(random.nextInt(101), random.nextInt(111), random.nextInt(121))); String rand = String.valueOf(getRandomString(random.nextInt(randString.length()))); randomString += rand; g.translate(random.nextInt(3), random.nextInt(3)); g.drawString(rand, 13 * i, 16); return randomString; } /*      * 绘制干扰线      */ private void drowLine(Graphics g) { int x = random.nextInt(width); int y = random.nextInt(height); int xl = random.nextInt(13); int yl = random.nextInt(15); g.drawLine(x, y, x + xl, y + yl); } /*      * 获取随机的字符      */ public String getRandomString(int num) { return String.valueOf(randString.charAt(num)); } } 最主要的使上面的工具直接就可以拿去使用,不用任何更改,如果自己想从新设置一些属性,可以直接在此代码中进行更改。

3、验证码的获取和登陆的验证

package com.qfant.admin;

import com.qfant.config.RandomValidateCode;
import com.qfant.utils.AjaxResult;
import com.qfant.wx.entity.User;
import com.qfant.wx.repository.UserMapper;
import org.apache.shiro.crypto.hash.Md5Hash;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;


import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;


@Controller
public class LoginController extends BaseController{

    @Autowired
    private UserMapper userRepository;

    /**
     * 登录页面生成验证码
     */
    @RequestMapping(value = "getVerify")
     public void getVerify(HttpServletRequest request, HttpServletResponse response){
        response.setContentType("image/jpeg");//设置相应类型,告诉浏览器输出的内容为图片  
        response.setHeader("Pragma", "No-cache");//设置响应头信息,告诉浏览器不要缓存此内容  
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expire", 0);
        RandomValidateCode randomValidateCode = new RandomValidateCode();
        try {
             randomValidateCode.getRandcode(request, response);//输出验证码图片方法  
        } catch (Exception e) {
            e.printStackTrace();
        }
    }



    /**
     * 登录校验
     *
     * @return
     */
    @RequestMapping("/login")
    public String login() {
        return "login";
    }


    @PostMapping("/submitlogin")
    @ResponseBody
    public AjaxResult ajaxLogin(String username, String password,String inputStr, HttpSession session) {
        User user=userRepository.getUserByUsername(username);
        String random = (String) session.getAttribute("RANDOMVALIDATECODEKEY");
        if(random.equals(inputStr.toUpperCase())){
            if(user!=null){
                String encryptPassword=encryptPassword(username,password,user.getSalt());
                if(encryptPassword.equals(user.getPassword())){
                    getRequest().getSession().setAttribute("user",user);
                    return  success();
                }else {
                    String msg = "用户或密码错误";
                    return error(msg);
                }
            }else {
                String msg = "用户不存在";
                return error(msg);
            }
        }else if(random==null){
            String msg = "验证码错误";
            return error(msg);
        }else{
            String msg = "验证码错误";
            return  error(msg);
        }
    }
    /**
     * 注销登录
     *
     * @param request
     * @return
     */
    @RequestMapping("/loginout")
    public String loginOut(HttpServletRequest request) {
        request.getSession().invalidate();
        return "login";
    }
    public  static String encryptPassword(String username, String password, String salt) {
        return new Md5Hash(username + password + salt).toHex().toString();
    }
}

4、拦截器

package com.qfant.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册拦截器
        LoginInterceptor loginInterceptor = new LoginInterceptor();
        InterceptorRegistration loginRegistry = registry.addInterceptor(loginInterceptor);
        // 拦截路径
        loginRegistry.addPathPatterns("/**");
        // 排除路径
        loginRegistry.excludePathPatterns("/");
        loginRegistry.excludePathPatterns("/login");
        loginRegistry.excludePathPatterns("/error");
        loginRegistry.excludePathPatterns("/submitlogin");
        loginRegistry.excludePathPatterns("/wx/**");
        loginRegistry.excludePathPatterns("/logout");
        // 排除资源请求
        loginRegistry.excludePathPatterns("/css/**");
        loginRegistry.excludePathPatterns("/js/**");
        loginRegistry.excludePathPatterns("/images/**");
        loginRegistry.excludePathPatterns("/fonts/**");
        loginRegistry.excludePathPatterns("/getVerify");
    }
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("forward:/login.html");
        registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
    }
}

最后总结我遇到的一些问题:

      第一:在撸码期间,验证码图片不能显示,那是因为我们把获取验证码的方法路径拦截了,放开就能够显示

      第二:登陆时首先是验证验证码是否正确

      第三:首次显示登录页时,输入正确验证码,但是显示错误,更换验证码后再输入就正确的问题,是因为获取了两次。等我们遇到的时候,可以检查是否获取重复。

以上是我在撸码期间遇到的问题,最终解决,完成了以上的登陆以及验证的代码,希望能够帮助撸友,若有疑问请留言,不喜勿喷哦,以上代码是借鉴网络大神的佳作,进行完成的。

 

 

 

你可能感兴趣的:(java简单的验证码登陆)