6. Spring Boot + Spring Security 短信发送功能(发送)

本文详细介绍了验证码的生成与处理机制,包括抽象的公共配置方法、验证码的具体逻辑接口及其实现,如图片验证码和短信验证码的生成与处理过程。通过具体的代码示例,展示了如何在项目中实现验证码的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

**采用了抽象的公共配置的方法
ValidateCodeController:前后跳转控制器
ValidateCodeProcessor: 验证码的具体逻辑接口
AbstractValidateCodeProcessor: 抽象类实现验证码的具体逻辑
ImageCodeProcessor: 图片验证码具体逻辑实现
SmsCodeProcessor: 短信验证码具体逻辑实现
ValidateCodeGenerator: 验证码生成接口
SmsCodeGenerator: 短信验证码生成类
ImageCodeGenerator:图片验证码生成类
**
在这里插入图片描述

  1. 项目目录
    在这里插入图片描述
  2. ImageCode.java 图片属性类

    package com.imooc.security.core.validate.code.image;
    
    import java.awt.image.BufferedImage;
    import java.time.LocalDateTime;
    
    import com.imooc.security.core.validate.code.ValidateCode;
    /**
     * 图片验证码
     * @author cjj
     * @date 2018年10月8日
     * @email 729165621@qq.com
     * @blog blog.youkuaiyun.com/qq_29451823
     */
    public class ImageCode extends ValidateCode{
    	
    	//图片
    	private BufferedImage image;
    	
    
    	public ImageCode(BufferedImage image, String code, int expireTime) {
    		super(code,expireTime);
    		this.image = image;
    	}
    	
    	public ImageCode(BufferedImage image, String code, LocalDateTime expireTime) {
    		super(code,expireTime);
    		this.image = image;
    	}
    	
    	public BufferedImage getImage() {
    		return image;
    	}
    	public void setImage(BufferedImage image) {
    		this.image = image;
    	}
    	
    }
  1. ValidateCode.java 短信属性类(因为短信类的部分属性与图片类一样,并且比图片类多)
package com.imooc.security.core.validate.code;
import java.time.LocalDateTime;
/**
 * 短信验证码
 * @author cjj
 * @date 2018年10月8日
 * @email 729165621@qq.com
 * @blog blog.youkuaiyun.com/qq_29451823
 */
public class ValidateCode {
	
	//随机数
	private  String code;
	//过期时间
	private LocalDateTime expireTime;
	
	public ValidateCode() {
		super();
	}
	
	public ValidateCode( String code, int expireTime) {
		super();
		this.code = code;
		this.expireTime = LocalDateTime.now().plusSeconds(expireTime);//生成一个过期的时间点
	}
	
	public ValidateCode(String code, LocalDateTime expireTime) {
		super();
		this.code = code;
		this.expireTime = expireTime;//生成一个过期的时间点
	}

	public String getCode() {
		return code;
	}
	public void setCode(String code) {
		this.code = code;
	}
	public LocalDateTime getExpireTime() {
		return expireTime;
	}
	public void setExpireTime(LocalDateTime expireTime) {
		this.expireTime = expireTime;
	}

	public boolean isExpried() {
		return LocalDateTime.now().isAfter(expireTime);//判断当前时间是否在过期时间之后
	}
	
	
}

  1. ValidateCodeGenerator.java验证码自动生成接口
package com.imooc.security.core.validate.code;
import org.springframework.web.context.request.ServletWebRequest;

public interface ValidateCodeGenerator {
	
	ValidateCode createImage(ServletWebRequest request);
	
}

  1. 、ImageCodeGenertor.java 图片验证码生成实现类
package com.imooc.security.core.validate.code.image;

import java.awt.Color;

import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.Random;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.context.request.ServletWebRequest;

import com.imooc.security.core.properties.SecurityProperties;
import com.imooc.security.core.validate.code.ValidateCodeGenerator;

@Component("imageCodeGenertor")
public class ImageCodeGenertor implements ValidateCodeGenerator{
	
	@Autowired
	private SecurityProperties securityProperties;

	 public ImageCode createImage(ServletWebRequest request) {
			
		 //获取用户设置的宽度
		int width = ServletRequestUtils.getIntParameter(request.getRequest(), "width",
				securityProperties.getValidate().getImage().getWidth());
		//获取用户设置的高度
		int height = ServletRequestUtils.getIntParameter(request.getRequest(), "height",
				securityProperties.getValidate().getImage().getHeight());

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

		Graphics g = image.getGraphics();

		Random random = new Random();

		g.setColor(getRandColor(200, 250));
		g.fillRect(0, 0, width, height);
		g.setFont(new Font("Times New Roman", Font.ITALIC, 20));
		g.setColor(getRandColor(160, 200));
		for (int i = 0; i < 155; i++) {
			int x = random.nextInt(width);
			int y = random.nextInt(height);
			int xl = random.nextInt(12);
			int yl = random.nextInt(12);
			g.drawLine(x, y, x + xl, y + yl);
		}

		String sRand = "";
		//生成随机数
		for (int i = 0; i < securityProperties.getValidate().getImage().getLength(); i++) {
			String rand = String.valueOf(random.nextInt(10));
			sRand += rand;
			g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));
			g.drawString(rand, 13 * i + 6, 16);
		}

		g.dispose();

		return new ImageCode(image, sRand, securityProperties.getValidate().getImage().getExprieIn());

	}
	/**
	 * 生成的随机条纹码
	 * @param fc
	 * @param bc
	 * @return
	 */
	private Color getRandColor(int fc, int bc) {
		Random random = new Random();
		if (fc > 255) {
			fc = 255;
		}
		if (bc > 255) {
			bc = 255;
		}
		int r = fc + random.nextInt(bc - fc);
		int g = fc + random.nextInt(bc - fc);
		int b = fc + random.nextInt(bc - fc);
		return new Color(r, g, b);

	}

	public SecurityProperties getSecurityProperties() {
		return securityProperties;
	}

	public void setSecurityProperties(SecurityProperties securityProperties) {
		this.securityProperties = securityProperties;
	}
	
	
}

  1. SmsCodeGenertor.java 短信验证码生成代码
package com.imooc.security.core.validate.code.sms;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.Random;

import org.apache.commons.lang.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.context.request.ServletWebRequest;

import com.imooc.security.core.properties.SecurityProperties;
import com.imooc.security.core.validate.code.ValidateCode;
import com.imooc.security.core.validate.code.ValidateCodeGenerator;
			   
@Component("smsCodeGenertor")
public class SmsCodeGenertor implements ValidateCodeGenerator{
	
	@Autowired
	private SecurityProperties securityProperties;

	 public ValidateCode createImage(ServletWebRequest request) {
		String code = RandomStringUtils.randomNumeric(securityProperties.getValidate().getSms().getLength());
		return new ValidateCode(code, securityProperties.getValidate().getSms().getExprieIn());
	}


	public SecurityProperties getSecurityProperties() {
		return securityProperties;
	}

	public void setSecurityProperties(SecurityProperties securityProperties) {
		this.securityProperties = securityProperties;
	}
	
	
}

  1. ValidateCodeProcessor.java验证码业务逻辑接口,验证码处理逻辑,都是分3步,第一步创建生成,第二步骤保存,第三步骤发送。所有所有不同的验证码只有发送的实现是不一样的,可以由具体的验证码子类实现。
package com.imooc.security.core.validate.code;

import org.springframework.web.context.request.ServletWebRequest;

/**
 * 效验码处理器,封装不同效验码的处理逻辑
 * @author cjj
 * @date 2018年11月5日
 * @email 729165621@qq.com
 * @blog blog.youkuaiyun.com/qq_29451823
 */
public interface ValidateCodeProcessor {
	
	/**
	 * 验证码放入session时的前缀
	 */
	String SESSION_KEY_PREFIX = "SESSION_KEY_FOR_CODE_";
	
	/**
	 * 创建效验码
	 * ServletWebRequest servlet的封装类,request何response都可以放在这里面
	 * @param request
	 * @throws Exception
	 */
	void create(ServletWebRequest request) throws Exception;
}

  1. AbstractValidateCodeProcesser.java 验证码处理逻辑抽象实现类
package com.imooc.security.core.validate.code.impl;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.social.connect.web.HttpSessionSessionStrategy;
import org.springframework.social.connect.web.SessionStrategy;
import org.springframework.web.context.request.ServletWebRequest;

import com.imooc.security.core.validate.code.ValidateCode;
import com.imooc.security.core.validate.code.ValidateCodeGenerator;
import com.imooc.security.core.validate.code.ValidateCodeProcessor;

public abstract class AbstractValidateCodeProcesser<C extends ValidateCode> implements ValidateCodeProcessor{
	
	/**
	 * 操作session的工具类
	 */ 
	private SessionStrategy sessionStrategy = new HttpSessionSessionStrategy();
	/**
	 * 收集系统中所有的{@link ValidateCodeGenerator} 接口的实现
	 *
	 */
	@Autowired
	private Map<String,ValidateCodeGenerator> validateCodeGenerators;
	
	
	public void create(ServletWebRequest request) throws Exception {
		C validateCode =  generate(request);//创建
		save(request,validateCode);//保存
		send(request,validateCode);//发送
	}
	
	/**
	 * 生成校验码
	 * @param request
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private  C generate(ServletWebRequest request) {
		String type = getProcessOrType(request).trim();
		//spring常见的依赖搜索,定向的去搜索某一个接口具体的实现							  
		ValidateCodeGenerator validateCodeGenerator = validateCodeGenerators.get(type+"CodeGenertor");
		C c = (C)validateCodeGenerator.createImage(request);
		return c;
	}
	/**
	 * 发送效验码,由子类实现
	 * @param request
	 * @param validateCode
	 * @throws Exception 
	 */
	protected  abstract void send(ServletWebRequest request, C validateCode) throws Exception;

	/**
	 * 保存效验码
	 * @param request
	 * @param validateCode
	 */
	private void save(ServletWebRequest request, C validateCode) {
		sessionStrategy.setAttribute(request, SESSION_KEY_PREFIX + getProcessOrType(request).toUpperCase(), validateCode);
	}
	
	/**
	 * 根据请求的URL获取校验的类型
	 * @param request
	 * @return
	 */
	private String getProcessOrType(ServletWebRequest request) {
		//从第一次出现该字符的位置往后面截取
		return StringUtils.substringAfter(request.getRequest().getRequestURI(), "/code/");
	}

	
	
}


  1. ImageCodeProcessor.java 图片验证码具体的发送逻辑
package com.imooc.security.core.validate.code.image;

import java.io.IOException;

import javax.imageio.ImageIO;

import org.springframework.stereotype.Component;
import org.springframework.web.context.request.ServletWebRequest;

import com.imooc.security.core.validate.code.impl.AbstractValidateCodeProcesser;

@Component("imageCodeProcessor")
public class ImageCodeProcessor extends AbstractValidateCodeProcesser<ImageCode>{
		
	protected void send(ServletWebRequest request, ImageCode imageCode) throws IOException {
	//图片验证码IO输出流就可以了
		ImageIO.write(imageCode.getImage(), "JPEG", request.getResponse().getOutputStream());
	}
}

  1. SmsCodeProcessor.java 短信验证码是由所使用的短信平台接口发送的,所有这里就模拟发送即可。
package com.imooc.security.core.validate.code.sms;

import javax.servlet.ServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.context.request.ServletWebRequest;

import com.imooc.security.core.validate.code.ValidateCode;
import com.imooc.security.core.validate.code.impl.AbstractValidateCodeProcesser;

@Component("smsCodeProcessor")
public class SmsCodeProcessor extends AbstractValidateCodeProcesser<ValidateCode>{
	/**
	 * 短信发送器
	 */
	@Autowired
	private SmsCodeSender smsCodeSender;
	
	protected  void send(ServletWebRequest request, ValidateCode validateCode) throws ServletRequestBindingException {
		String mobile = ServletRequestUtils.getRequiredStringParameter(request.getRequest(), "mobile");
		smsCodeSender.send(mobile, validateCode.getCode());
	};
	
}

/*具体的发送,手动模拟*/
package com.imooc.security.core.validate.code.sms;

public interface SmsCodeSender {

	void send (String mobile, String code);
}



package com.imooc.security.core.validate.code.sms;

public class DefaultSmsCodeSender implements SmsCodeSender {

	@Override
	public void send(String mobile, String code) {
		System.out.println("像手机"+mobile+"发送 选项验证码"+code);
	}

}


  1. ValidateCodeBeanConfig.java 使用@Configuration配置生成Bean,并且可以验证其他注解的Bean
package com.imooc.security.core.validate.code;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.imooc.security.core.properties.SecurityProperties;
import com.imooc.security.core.validate.code.image.ImageCodeGenertor;
import com.imooc.security.core.validate.code.sms.DefaultSmsCodeSender;
import com.imooc.security.core.validate.code.sms.SmsCodeSender;

@Configuration
public class ValidateCodeBeanConfig {
	
	@Autowired
	private SecurityProperties securityProperties;
	
	@Bean							
	@ConditionalOnMissingBean(name="imageCodeGenertor")//如果初始化spring容器的时候,里面有imageCodeGenerator则就不用加载下面的内容
	public ValidateCodeGenerator imageCodeGenertor() {
		ImageCodeGenertor codeGenertor = new ImageCodeGenertor();
		codeGenertor.setSecurityProperties(securityProperties);
		return codeGenertor;
	}
	
	@Bean
	@ConditionalOnMissingBean(SmsCodeSender.class)
	public SmsCodeSender smsCodeSender() {
		return new DefaultSmsCodeSender();
	}
}

  1. BrowserSecurityConfig.java 安全框架配置,只需要添加验证码访问路径就行了
			.and()
			.authorizeRequests()//对请求做一个授权
			.antMatchers("/authentication/require"
					,securityProperties.getBrowser().getLoginPage()
					,"/code/*").permitAll()//访问这个页面的时候不需要授权
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值