欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

SpringScurity实现图片验证码功能

程序员文章站 2022-04-27 11:02:50
前言整个小案例采用的是ssm+jsp+springscurity的技术1.导入依赖坐标 2.编写验证码功能我的验证码部分代码是写在后台的,并且封装成了一个工具类package utils;import javax.imageio.ImageIO;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;imp......

 

 

前言

整个小案例采用的是ssm+jsp+springscurity的技术

1.导入依赖坐标

               

2.编写验证码功能

我的验证码部分代码是写在后台的,并且封装成了一个工具类

package utils;
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;

public class CheckCodeUtils {
    public static final String CHECKCODE_KEY = "checkCode_key";
    private static Random random=new Random();

    private static String randStr="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private static int width=80 ;
    private static int height=26 ;
    private static int lineNum=10 ;
    private static int strNum=4 ;

    private String randString;


    //获取随机验证码
    public   void getCheckCode(HttpServletRequest request, HttpServletResponse response){
        HttpSession session = request.getSession();
        BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_BGR);
        Graphics graphics = image.getGraphics();
        graphics.fillRect(0,0,width,height);
        graphics.setFont(new Font("Times New Roman",Font.ROMAN_BASELINE,18));
        graphics.setColor(getRandColor(160, 200));
        //绘制干扰线
        for(int i=0;i<=lineNum;i++){
            drowLine(graphics);
        }
        //绘制随机字符
         randString = "";
        for(int i=1;i<=strNum;i++){
            randString=drowString(graphics,randString,i);
        }
        session.removeAttribute(CHECKCODE_KEY);
        session.setAttribute(CHECKCODE_KEY, randString);
        graphics.dispose();
        try {
            //将内存中的图片通过流动形式输出到客户端
            ImageIO.write(image, "JPEG", response.getOutputStream());

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /*
     * 获得字体
     */
    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);
    }

    /*
     * 绘制字符串.
     */
    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(randStr.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(randStr.charAt(num));
    }
/*比较*/
    public String getRandString() {
        return randString;
    }

    public void setRandString(String randomString) {
        this.randString = randomString;
    }
}

类似的图片验证码的工具类网络上也是一大堆,可以自行查找

3.前端页面

<!--验证码栏-->
        <div class="usernameWrapDiv">
            <div class="layui-form-item layui-inline" >
                <label class="layui-form-label"><i class="layui-icon layui-icon-vercode"></i>验证: </label>
                    <div class="cardDiv">
                        <input id="loginCard" class="layui-input cardInput" type="text" name="loginCard" placeholder="输入验证码">
                    </div>
                    <div class="codeDiv">
                        <img name="imageCode" src="${pageContext.request.contextPath}/user/checkCode.do" alt="" width="100" height="32" class="layui-input codeInput" style="height:37.99px;cursor:pointer;"onclick="this.src=this.src+'?'">
                    </div>
            </div>
        </div>

4.Controller

@Controller
@RequestMapping("/user")
public class UserController {

    CheckCodeUtils utils;

    @RequestMapping("/checkCode.do")
    public void checkCode(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //设置相应类型,告诉浏览器输出的内容为图片
        utils = new CheckCodeUtils() ;
        response.setContentType("image/jpeg");

        //设置响应头信息,告诉浏览器不要缓存此内容
        response.setHeader("pragma", "no-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expire", 0);
        try {
            utils.getCheckCode(request, response);//输出图片方法
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}

5.实现自定义的图片验证码filter

 

public class ImageCodeAuthenticationFilter extends OncePerRequestFilter {

    private AuthenticationFailureHandler authenticationFailureHandler;

    public void setAuthenticationFailureHandler(AuthenticationFailureHandler authenticationFailureHandler) {
        this.authenticationFailureHandler = authenticationFailureHandler;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        if (request.getRequestURI().contains("/securityLogin")) {
            try {
                String inputImageCode = request.getParameter("loginCard");
                String outputImageCode = (String) request.getSession().getAttribute("checkCode_key");
                
                if (StringUtils.isEmpty(inputImageCode.trim())) {
                    throw new ImageCodeException("验证码必须输入");
                }
                if (!inputImageCode.trim().equalsIgnoreCase(outputImageCode.trim())) {
                    throw new ImageCodeException("验证码错误");
                }
            }catch (AuthenticationException e){
                authenticationFailureHandler.onAuthenticationFailure(request,response,e);
                return;
            }
        }
        filterChain.doFilter(request,response);
    }
}

图片验证码异常类 


public class ImageCodeException  extends AuthenticationException {
    public ImageCodeException(String msg, Throwable t) {
        super(msg, t);

    }

    public ImageCodeException(String msg) {
        super(msg);

    }
}

自定义权限认证失败处理类


public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {
    private ObjectMapper objectMapper = new ObjectMapper();



    @Override

    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
        Map map = new HashMap();

        map.put("success", false);

        map.put("errorMsg", e.getMessage());

        String str = objectMapper.writeValueAsString(map);

        response.setContentType("text/json;charset=utf-8");
        request.getRequestDispatcher("/failer.jsp").forward(request,response);

    }

}

 如果认证失败直接是转发到failer.jsp界面

   request.getRequestDispatcher("/failer.jsp").forward(request,response);

6.SpringSecurity框架配置文件的修改

 // 定义类型为imageCodeAuthenticationFilter的Filter 并且在 FORM_LOGIN_FILTER (通俗点理解成表单登录Filter)前先过滤
<security:custom-filter ref="imageCodeAuthenticationFilter" before="FORM_LOGIN_FILTER"/>


//将ImageCodeAuthenticationFilter和MyAuthenticationFailureHandler 交给Spring容器来进行管理

<bean id="imageCodeAuthenticationFilter" class="security.ImageCodeAuthenticationFilter">

        <property name="authenticationFailureHandler" ref="myAuthenticationFailureHandler"/>

    </bean>
    <bean id="myAuthenticationFailureHandler" class="security.MyAuthenticationFailureHandler"/>

具体可以参考:https://blog.csdn.net/love1793912554/article/details/104298677

我觉得这里面一系列关于SpringSecurity的文章都写的很清晰也比较实用

 

 

本文地址:https://blog.csdn.net/weixin_44451209/article/details/110819253

相关标签: java ssm