前言:认证在互联网中会常常见到,其主要做用是安全问题中防止恶意破解、刷票等。在系统开发中认证的实现也有不少种,什么手机短信认证,邮箱认证等。在这里我使用最基本的验证码的形式进行认证,下面例出过程。html
建立一个简单的验证码生成器,经过流的方式将随机字体、随机背景色、干扰线、随机字符串,夹杂在一块儿造成验证码图片vue
import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.OutputStream; import java.util.Random; /** * 自定义验证码类 */ public class VerifyCode { private int width = 100; //生成验证码图片的宽度 private int height = 40; //生成验证码图片的高度 private String[] fontNames = {"宋体","楷体","隶书","微软雅黑"}; private Color bgColor = new Color(255,255,255); //定义验证码图片的背景色 private Random random = new Random(); private String codes = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; private String text; //记录随机字符串 /** * 获取随机一个颜色 * @return */ private Color randomColor(){ int red = random.nextInt(150); int green = random.nextInt(150); int blue = random.nextInt(150); return new Color(red,green,blue); } /** * 获取随机一个字体 * @return */ private Font randomFont(){ String name = fontNames[random.nextInt(fontNames.length)]; int style = random.nextInt(4); int size =random.nextInt(5)+24; return new Font(name,style,size); } /** * 获取随机一个字符 * @return */ private char randomChar(){ return codes.charAt(random.nextInt(codes.length())); } /** * 建立一个空白的BufferedImage对象 * @return */ private BufferedImage createImage(){ BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics2D g2 = (Graphics2D)image.getGraphics(); g2.setColor(bgColor); g2.fillRect(0,0,width,height); return image; } /** * 绘制干扰线 */ private void drawLine(BufferedImage image){ Graphics2D g2 = (Graphics2D) image.getGraphics(); int num = 5; for (int i = 0 ;i < num ; i++){ int x1 = random.nextInt(width); int y1 = random.nextInt(height); int x2 = random.nextInt(width); int y2 = random.nextInt(height); g2.setColor(randomColor()); g2.setStroke(new BasicStroke(1.5f)); g2.drawLine(x1, y1, x2, y2); } } /** * 绘制验证码 * @return */ public BufferedImage getImage(){ BufferedImage image = createImage(); Graphics2D g2 = (Graphics2D) image.getGraphics(); StringBuffer sb = new StringBuffer(); for (int i = 0 ; i < 4 ; i++){ String s = randomChar() + ""; sb.append(s); g2.setColor(randomColor()); g2.setFont(randomFont()); float x = i * width * 1.0f / 4; g2.drawString(s,x,height - 15); } this.text = sb.toString(); drawLine(image); return image; } public String getText(){ return text; } /** * 用流传输方法 * @return */ public static void output(BufferedImage image, OutputStream out) throws IOException { ImageIO.write(image,"JPEG",out); } }
建立VerifyCode验证码生成器实例,将text(随机字符串)存入session中,将图片用流的方式传入前段java
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.awt.image.BufferedImage; import java.io.IOException; @RestController public class VerifyCodeController { @GetMapping("/vercode") public void code(HttpServletRequest req, HttpServletResponse resp) throws IOException { //建立验证码生成器实例取得生成图片和随机字符串 VerifyCode vc = new VerifyCode(); BufferedImage image = vc.getImage(); String text = vc.getText(); //随机字符串存入session中 HttpSession session = req.getSession(); session.setAttribute("index_code",text); //用流传输 VerifyCode.output(image,resp.getOutputStream()); } }
前段我这里使用的是vue框架(使用什么框架不是问题,姑且提一下),img图片中src路劲调用web
<img src="/vercode" alt="">
启动服务器,测试,获取成功
spring
我这里作登陆认证,表单加入验证码输入安全
<tr> <td> <el-tag>验证码</el-tag> </td> <td> <el-input size="mini" v-model="user.code" pleceholder="请输入验证码"></el-input> </td> <td> <img src="/vercode" alt=""> </td> </tr>
这里只提取验证码相关的:服务器
自定义过滤器,继承GenericFilterBean,重写doFilter方法session
@Component public class VerifyCodeFilter extends GenericFilterBean { //绑定登陆路径 private String defaultFilterProcessUrl = "/doLogin"; @Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) resp; if ("POST".equalsIgnoreCase(request. getMethod()) && defaultFilterProcessUrl.equals(request.getServletPath())){ String requestCaptcha = request.getParameter("code"); String genCaptcha = (String) request.getSession().getAttribute("index_code"); if(StringUtils.isEmpty(requestCaptcha)){ throw new AuthenticationServiceException("验证码不能为空!"); } if (!genCaptcha.toLowerCase().equals(requestCaptcha.toLowerCase())){ throw new AuthenticationServiceException("验证码错误!"); } } chain.doFilter(request,response); } }
继承WebSecurityConfigurerAdapter类,重写认证方法app
@Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired VerifyCodeFilter verifyCodeFilter; @Override public void configure(WebSecurity web) throws Exception { //防止验证图片被拦截 web.ignoring().antMatchers("/vercode"); } @Override protected void configure(HttpSecurity http) throws Exception { //对前段获取到的验证数据进行验证 http.addFilterBefore(verifyCodeFilter,UsernamePasswordAuthenticationFilter.class); http.authorizeRequests() //省略帐号密码认证 ... ... ... .permitAll() .and() .csrf().disable() } }
登陆测试 框架
此次就到这里,有什么问题或建议能够在下面评论。