战国无双-策略国战活动站

springboot实现验证码功能

- 国战实录

转载自 : www.javaman.cn

1、编写工具类生成4位随机数

该工具类主要生成从0-9,a-z,A-Z范围内产生的4位随机数

/**

* 产生4位随机字符串

*/

public static String getCheckCode() {

String base = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

int size = base.length();

Random r = new Random();

StringBuffer sb = new StringBuffer();

for (int i = 1; i <= 4; i++) {

//产生0到size-1的随机值

int index = r.nextInt(size);

//在base字符串中获取下标为index的字符

char c = base.charAt(index);

//将c放入到StringBuffer中去

sb.append(c);

}

return sb.toString();

}

2、编写常量类

用户常量的绑定,所有的常量都可以在ConfigConsts中定义,方便管理。

import java.util.Arrays;

import java.util.List;

public interface ConfigConsts {

/**

* 验证码存session

*/

String IMAGE_CODE_SESSION = "IMAGE_CODE";

}

3、获取验证码接口

这段代码的主要作用是为用户生成一个图片验证码,并将其显示在浏览器中。当调用该代码对应的URL时,服务器会创建一个包含随机验证码的图片,并将此验证码存储在用户的会话中,然后将该图片发送给用户的浏览器显示

/**

* 验证码

*/

@RequestMapping("/getImgCode")

public void getImgCode(HttpServletRequest request, HttpServletResponse response) {

int width = 80;

int height = 30;

BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

//获取画笔

Graphics graphics = image.getGraphics();

//设置画笔颜色为白色

graphics.setColor(Color.white);

//填充图片

graphics.fillRect(0, 0, width, height);

//设置画笔颜色为黑色

graphics.setColor(Color.black);

//设置字体的小大

graphics.setFont(new Font("黑体", Font.BOLD, 24));

//产生4个随机验证码

String checkCode = CommonUtil.getCheckCode();

//将验证码放入HttpSession中

HttpSession session = request.getSession();

session.setAttribute(ConfigConsts.IMAGE_CODE_SESSION, checkCode);

//向图片上写入验证码

graphics.drawString(checkCode, 15, 25);

//将内存中的图片输出到浏览器

try {

response.setContentType("image/png");

ImageIO.write(image, "PNG", response.getOutputStream());

} catch (IOException e) {

e.printStackTrace();

}

}

4、controller跳转到登录页

对“/loginPage”的GET请求,并将用户重定向到登录页面。当调用这个URL时,系统会返回一个名为"login"的视图(通常是一个HTML页面),这个视图通常用于显示登录表单,让用户输入用户名和密码等信息。

/**

* 跳转到登陆页面

* @return 登陆页面

*/

@GetMapping("/loginPage")

public String loginPage(){

return "login";

}

5、登录界面

在Web页面上实现一个图形验证码的输入功能

HTML部分:

创建一个表单项,内部包含两列(使用layui的栅格系统)。

在第一列中,有一个标签和一个文本输入框。标签用于显示一个验证码图标,输入框用于用户输入图形验证码。

在第二列中,有一个图片元素用于显示图形验证码图片。

JavaScript部分:

配置layui的静态资源路径和主入口模块。

初始化时,调用getImgCode函数加载验证码图片,并渲染表单。

getImgCode函数通过Ajax请求从服务器获取验证码图片,并将其显示在页面上的图片元素中。

这段代码主要利用了layui框架来实现页面的布局和交互,同时通过JavaScript和Ajax实现与服务器的通信,以获取并显示图形验证码。

6、验证码过滤

校验验证码的过滤器,基于Java的Spring框架。

该过滤器继承了OncePerRequestFilter,确保每次请求只被过滤一次。

在doFilterInternal方法中,它首先检查请求是否是登录请求(通过检查请求路径是否为"/login"以及请求方法是否为"POST")。

如果是登录请求,它会调用validate方法来校验验证码。

validate方法从请求中获取验证码,然后与会话中存储的验证码进行比对。如果验证码不存在、为空或不匹配,将抛出异常。

如果验证码校验失败,过滤器会捕获异常,并向响应中写入错误信息(以JSON格式)。

如果请求不是登录请求,过滤器不会进行验证码校验,直接让请求继续向下执行(通过调用filterChain.doFilter)。

如果登录请求成功通过验证码校验,代码会继续执行后续的过滤器或处理器。

@Component

public class ValidateCodeFilter extends OncePerRequestFilter {

@Override

protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {

// 登陆请求

if ("/login".equals(httpServletRequest.getServletPath()) &&

"POST".equalsIgnoreCase(httpServletRequest.getMethod())){

try {

validate(httpServletRequest);

} catch (Exception exception) {

httpServletResponse.setCharacterEncoding("utf-8");

httpServletResponse.setContentType("application/json;charset=UTF-8");

PrintWriter writer = httpServletResponse.getWriter();

writer.write(JSON.toJSONString(Result.failure(exception.getMessage())));

writer.flush();

return;

}

}

// 不是一个登录请求,不做校验 直接通过

filterChain.doFilter(httpServletRequest, httpServletResponse);

}

private void validate(HttpServletRequest request) {

String code = request.getParameter("code");

if (StringUtils.isBlank(code)){

throw new RuntimeException("验证码不能为空");

}

Object checkCode = request.getSession(false).getAttribute(ConfigConsts.IMAGE_CODE_SESSION);

if (Objects.isNull(checkCode)) {

throw new RuntimeException("验证码不存在");

}

if (!StringUtils.equalsIgnoreCase(code,checkCode.toString())) {

throw new RuntimeException("验证码不匹配");

}

request.getSession(false).removeAttribute(ConfigConsts.IMAGE_CODE_SESSION);

}

}

7、集成mysecurity

集成Spring Security的安全配置类,用于Web应用的安全性设置。

通过@EnableWebSecurity和@Configuration注解,启用并配置Spring Security。

使用@EnableGlobalMethodSecurity(prePostEnabled = true)来启用全局方法级别的安全性,允许使用例如@PreAuthorize和@PostAuthorize等注解。

定义了一个名为MySecurityConfig的配置类,该类继承自WebSecurityConfigurerAdapter,用于定制安全性设置。

通过@Autowired注入了一个名为validateCodeFilter的验证码过滤器实例。

在configure(HttpSecurity http)方法中,对应用的安全性进行了详细配置:

允许所有人访问/loginPage和/getImgCode这两个路径,不进行任何安全检查。

对所有其他请求,需要用户进行身份验证(即需要登录后才能访问)。

在用户名和密码验证过滤器之前,添加了一个自定义的验证码过滤器(validateCodeFilter),用于在登录过程中校验验证码。

这段代码的主要目的是增强Web应用的安全性,通过添加验证码校验来防止自动化登录尝试和暴力破解,并限制了只有经过身份验证的用户才能访问应用的受保护资源。

@Configuration

@EnableWebSecurity

@EnableGlobalMethodSecurity(prePostEnabled = true)

public class MySecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired

private ValidateCodeFilter validateCodeFilter;

@Override

protected void configure(HttpSecurity http) throws Exception {

http.authorizeRequests()

// 放过

.antMatchers("/loginPage", "/getImgCode").permitAll()

.anyRequest().authenticated()

.and()

// 过滤登录验证码

.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class)

}

运行结果如下:

如何打开.xd文件?一键解决打开困扰!
凉是哪里的车牌号,凉是哪个省车牌的简称-妙妙懂车,凉是哪里的车牌号?