springboot对接第三方短信接口整合redis,ActiveMQ
2018-03-17 17:44
856 查看
1.对接第三方短信接口需要模拟一个http请求
用http-client这个包来操作。
在pom.xml文件中加入http-client的包依赖<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>2.新建一个httputil类来模拟get/post请求
void sendVercode(String mobile, String ip) throws ustomException;
}
Service实现类:@Service
@Slf4j
public class UserServiceImpl implements UserService {
private static final String VERIFYCODE_PREFIX = "verify.code.";
private static final String SMS_QUEUE ="sms.queue"
@Autowired
private CommonCacheUtil cacheUtil;
@Autowired
private SmsProcessor smsProcessor;
@Override
public void sendVercode(String mobile, String ip) throws CustomException {
String verCode = RandomNumberCode.verCode();
int result = cacheUtil.cacheForVerificationCode(VERIFYCODE_PREFIX+mobile,verCode,"reg",60,ip);
if (result == 1) {
log.info("当前验证码未过期,请稍后重试");
throw new CustomException("当前验证码未过期,请稍后重试");
} else if (result == 2) {
log.info("超过当日验证码次数上线");
throw new CustomException("超过当日验证码次数上限");
} else if (result == 3) {
log.info("超过当日验证码次数上限 {}", ip);
throw new CustomException(ip + "超过当日验证码次数上限");
}
log.info("Sending verify code {} for phone {}", verCode, mobile);
//校验通过 发送短信 发消息到队列
Destination destination = new ActiveMQQueue(SMS_QUEUE);
Map<String,String> smsParam = new HashMap<>();
smsParam.put("mobile",mobile);
smsParam.put("tplId", Constants.MDSMS_VERCODE_TPLID);
smsParam.put("vercode",verCode);
String message = JSON.toJSONString(smsParam);
smsProcessor.sendSmsToQueue(destination,message);
} }RandomNumberCode方法生成四位随机验证码public class RandomNumberCode {
public static String verCode(){
Random random =new Random();
return StringUtils.substring(String.valueOf(random.nextInt()*-10), 2, 6);
}
public static String randomNo(){
Random random =new Random();
return String.valueOf(Math.abs(random.nextInt()*-10));
}
}将验证码信息存到redis缓存中
springboot整合redis
添加配置文件在application.yml中redis:
host: 127.0.0.1
port: 6379
auth:
max-idle: 5
max-total: 10
max-wait-millis: 3000
新建一个类来获取变量值:@Data //该注释自动帮你完成get/set方法,在pom.xml文件引入org.projectlombok包,加速开发
/*注入*/
@Component
public class Parameters {
/*****redis config start*******/
@Value("${redis.host}")
private String redisHost;
@Value("${redis.port}")
private int redisPort;
@Value("${redis.auth}")
private String redisAuth;
@Value("${redis.max-idle}")
private int redisMaxTotal;
@Value("${redis.max-total}")
private int redisMaxIdle;
@Value("${redis.max-wait-millis}")
private int redisMaxWaitMillis;
/*****redis config end*******/
}
创建JedisPoolWrapper类@Component
@Slf4j
public class JedisPoolWrapper {
private JedisPool jedisPool = null;
@Autowired
private Parameters parameters;
@PostConstruct
public void init() throws CustomException {
try{
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxIdle(parameters.getRedisMaxIdle());
config.setMaxTotal(parameters.getRedisMaxTotal());
config.setMaxWaitMillis(parameters.getRedisMaxWaitMillis());
jedisPool = new JedisPool(config,parameters.getRedisHost(),parameters.getRedisPort(),2000);
}catch (Exception e){
log.error("Fail to initialize redis pool",e);
throw new CustomException("初始化redis失败");
}
}
public JedisPool getJedisPool(){
return jedisPool;
}
}创建一个CommonCacheUtil工具类@Component
@Slf4j
public class CommonCacheUtil {
private static final String TOKEN_PREFIX = "token.";
private static final String USER_PREFIX = "user.";
@Autowired
private JedisPoolWrapper jedisPoolWrapper;
/**
* 缓存 key value 永久
* @param key
* @param value
*/
public void cache(String key, String value) {
try {
JedisPool pool = jedisPoolWrapper.getJedisPool();
if (pool != null) {
try (Jedis Jedis = pool.getResource()) {
Jedis.select(0);//选择redis第0片区
Jedis.set(key, value);
}
}
} catch (Exception e) {
log.error("Fail to cache value", e);
}
}
/**
* 获取缓存key
* @param key
* @return
*/
4000
public String getCacheValue(String key) {
String value = null;
try {
JedisPool pool = jedisPoolWrapper.getJedisPool();
if (pool != null) {
try (Jedis Jedis = pool.getResource()) {
Jedis.select(0);
value = Jedis.get(key);
}
}
} catch (Exception e) {
log.error("Fail to get cached value", e);
}
return value;
}
/**
* 设置key value 以及过期时间
* @param key
* @param value
* @param expiry
* @return
*/
public long cacheNxExpire(String key, String value, int expiry) {
long result = 0;
try {
JedisPool pool = jedisPoolWrapper.getJedisPool();
if (pool != null) {
try (Jedis jedis = pool.getResource()) {
jedis.select(0);
result = jedis.setnx(key, value);
jedis.expire(key, expiry);
}
}
} catch (Exception e) {
log.error("Fail to cacheNx value", e);
}
return result;
}
/**
* 删除缓存key
* @param key
*/
public void delKey(String key) {
JedisPool pool = jedisPoolWrapper.getJedisPool();
if (pool != null) {
try (Jedis jedis = pool.getResource()) {
jedis.select(0);
try {
jedis.del(key);
} catch (Exception e) {
log.error("Fail to remove key from redis", e);
}
}catch (Exception e) {
log.error("Fail to remove key from redis", e);
}
}
}
/**
* 缓存手机验证码专用 限制了发送次数
* @return 1 当前验证码未过期 2 手机号超过当日验证码次数上限 3 ip超过当日验证码次数上线
*/
public int cacheForVerificationCode(String key, String verCode, String type, int second, String ip) throws Exception {
JedisPool pool = jedisPoolWrapper.getJedisPool();
if (pool != null) {
try (Jedis jedis = pool.getResource()) {
jedis.select(0);
try {
String ipKey = "ip."+ip;
if(ip==null){
return 3;
} else {
String ipSendCount = jedis.get(ipKey);
try {
if (ipSendCount != null && Integer.parseInt(ipSendCount) >= 10) {
return 3;
}
} catch (NumberFormatException e) {
log.error("Fail to process ip send count", e);
return 3;
}
long succ = jedis.setnx(key, verCode);
if (succ == 0) {
return 1;
}
String sendCount = jedis.get(key + "." + type);
try {
if (sendCount != null && Integer.parseInt(sendCount) >= 10) {
jedis.del(key);
return 2;
}
} catch (NumberFormatException e) {
log.error("Fail to process send count", e);
jedis.del(key);
return 2;
}
try {
jedis.expire(key, second);
long val = jedis.incr(key + "." + type);
if (val == 1) {
jedis.expire(key + "." + type, 86400);
}
jedis.incr(ipKey);
if (val == 1) {
jedis.expire(ipKey, 86400);
}
} catch (Exception e) {
log.error("Fail to cache data into redis", e);
}
}
} catch (Exception e) {
log.error("Fail to set vercode to redis", e);
throw e;
}
} catch (Exception e) {
log.error("Fail to cache for expiry", e);
throw new Exception("Fail to cache for expiry");
}
}
return 0;
}
}
新建一个短信接口public interface SmsSender {
void sendSms(String phone,String tplId,String params);
}实现类,依据官方demo作修改@Service("verCodeService")
@Slf4j
public class MiaoDiSmsSender implements SmsSender{
private static String operation = "/industrySMS/sendSMS";
@Override
public void sendSms(String phone,String tplId,String params){
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
String timestamp = sdf.format(new Date());
String sig = MD5Util.getMD5(Constants.MDSMS_ACCOUNT_SID +Constants.MDSMS_AUTH_TOKEN +timestamp);
String url = Constants.MDSMS_REST_URL +operation;
Map<String,String> param = new HashMap<>();
param.put("accountSid",Constants.MDSMS_ACCOUNT_SID);
param.put("to",phone);
param.put("templateid",tplId);
param.put("param",params);
param.put("timestamp",timestamp);
param.put("sig",sig);
param.put("respDataType","json");
String result = HttpUtil.post(url,param);
JSONObject jsonObject = JSON.parseObject(result);
if(!jsonObject.getString("respCode").equals("00000")){
log.error("fail to send sms to "+phone+":"+params+":"+result);
}
} catch (Exception e) {
log.error("fail to send sms to "+phone+":"+params);
}
}
}整合ActiveMQ,在pom.xml文件中加入包依赖<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>新建一个消息生产者SmsProcessor类@Component("smsProcessor")
public class SmsProcessor {
@Autowired
private JmsMessagingTemplate jmsTemplate;
@Autowired
@Qualifier("verCodeService")
private SmsSender smsSender;
public void sendSmsToQueue(Destination destination, final String message){
jmsTemplate.convertAndSend(destination, message);
}
@JmsListener(destination="sms.queue")
public void doSendSmsMessage(String text){
JSONObject jsonObject = JSON.parseObject(text);
smsSender.sendSms(jsonObject.getString("mobile"),jsonObject.getString("tplId"),jsonObject.getString("vercode"));
}
}Controller代码:@RequestMapping("/sendVercode")
public ApiResult sendVercode(@RequestBody User user, HttpServletRequest request){
ApiResult resp = new ApiResult();
try {
userService.sendVercode(user.getMobile(),getIpFromRequest(request));
}catch(CustomException e){
resp.setCode(Constants.RESP_STATUS_INTERNAL_ERROR);
resp.setMessage(e.getMessage());
}
catch(CustomException e){
log.error("Fail to login",e);
resp.setCode(Constants.RESP_STATUS_INTERNAL_ERROR);
resp.setMessage("内部错误");
}
return resp;
}
User类@Data
public class User {
private Long id;
private String nickname;
private String mobile;
private String headImg;
private Byte verifyFlag;
private Byte enableFlag;
}
统一返回数据ApiResult类public class ApiResult<T> {
private int code = Constants.RESP_STATUS_OK;
private String message;
private T data;
}
自定义异常类:CustomExceptionpublic class CustomException extends Exception {
public CustomException(String message){
super(message);
}
}
常量类:Constantspublic class Constants {
/**自定义状态码 start**/
public static final int RESP_STATUS_OK = 200;
public static final int RESP_STATUS_NOAUTH = 401;
public static final int RESP_STATUS_INTERNAL_ERROR = 500;
public static final int RESP_STATUS_BADREQUEST = 400;
/**秒滴SMS start**/
public static final String MDSMS_ACCOUNT_SID = "填写自己的SID";
public static final String MDSMS_AUTH_TOKEN = "填写自己TOKEN";
public static final String MDSMS_REST_URL = "https://api.miaodiyun.com/20150822";
public static final String MDSMS_VERCODE_TPLID = "模板编号";
/**秒滴SMS end**/
public static final String REQUEST_TOKEN_KEY = "user-token";
public static final String REQUEST_VERSION_KEY = "version"
}
考虑短信接口的安全性
1.IP 根据IP来判定 超过十次 不发送验证码
手机号 同一个手机号 不能超过多少次
通过调用redis工具类中的cacheForVerificationCode方法
2.获取真正的ip+本机ip测试(ngnix负载均衡,请求分发)protected String getIpFromRequest(HttpServletRequest request) {
String ip = request.getHeader("x-forwarded-for");
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
ip = request.getHeader("Proxy-Client-IP");
}
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
ip = request.getHeader("WL-Proxy-Client-IP");
}
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
ip = request.getRemoteAddr();
}
return ip.equals("0:0:0:0:0:0:0:1")?"127.0.0.1":ip;
}
用http-client这个包来操作。
在pom.xml文件中加入http-client的包依赖<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>2.新建一个httputil类来模拟get/post请求
import lombok.extern.slf4j.Slf4j; import org.apache.http.HttpEntity; import org.apache.http.NameValuePair; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.message.BasicNameValuePair; import org.apache.http.util.EntityUtils; import java.net.URLEncoder; import java.util.ArrayList; import java.util.List; import java.util.Map; @Slf4j public class HttpUtil { private static final String ENCODING = "UTF-8"; public static String post(String url, Map<String, String> paramsMap) { CloseableHttpClient client = HttpClients.createDefault(); String responseText = ""; CloseableHttpResponse response = null; try { HttpPost method = new HttpPost(url); if (paramsMap != null) { List<NameValuePair> paramList = new ArrayList<NameValuePair>(); for (Map.Entry<String, String> param : paramsMap.entrySet()) { NameValuePair pair = new BasicNameValuePair(param.getKey(), param.getValue()); paramList.add(pair); } method.setEntity(new UrlEncodedFormEntity(paramList, ENCODING)); } response = client.execute(method); HttpEntity entity = response.getEntity(); if (entity != null) { responseText = EntityUtils.toString(entity); } } catch (Exception e) { log.error("http request failed",e); } finally { try { response.close(); } catch (Exception e) { log.error("",e); } } return responseText; } public static String get(String url, Map<String, String> paramsMap) { CloseableHttpClient client = HttpClients.createDefault(); String responseText = ""; CloseableHttpResponse response = null; try { String getUrl = url+"?"; if (paramsMap != null) { for (Map.Entry<String, String> param : paramsMap.entrySet()) { getUrl += param.getKey() + "=" + URLEncoder.encode(param.getValue(), ENCODING)+"&"; } } HttpGet method = new HttpGet(getUrl); response = client.execute(method); HttpEntity entity = response.getEntity(); if (entity != null) { responseText = EntityUtils.toString(entity); } } catch (Exception e) { log.error("http request failed",e); } finally { try { response.close(); } catch (Exception e) { log.error("",e); } } return responseText; } }Service接口:public interface UserService {
void sendVercode(String mobile, String ip) throws ustomException;
}
Service实现类:@Service
@Slf4j
public class UserServiceImpl implements UserService {
private static final String VERIFYCODE_PREFIX = "verify.code.";
private static final String SMS_QUEUE ="sms.queue"
@Autowired
private CommonCacheUtil cacheUtil;
@Autowired
private SmsProcessor smsProcessor;
@Override
public void sendVercode(String mobile, String ip) throws CustomException {
String verCode = RandomNumberCode.verCode();
int result = cacheUtil.cacheForVerificationCode(VERIFYCODE_PREFIX+mobile,verCode,"reg",60,ip);
if (result == 1) {
log.info("当前验证码未过期,请稍后重试");
throw new CustomException("当前验证码未过期,请稍后重试");
} else if (result == 2) {
log.info("超过当日验证码次数上线");
throw new CustomException("超过当日验证码次数上限");
} else if (result == 3) {
log.info("超过当日验证码次数上限 {}", ip);
throw new CustomException(ip + "超过当日验证码次数上限");
}
log.info("Sending verify code {} for phone {}", verCode, mobile);
//校验通过 发送短信 发消息到队列
Destination destination = new ActiveMQQueue(SMS_QUEUE);
Map<String,String> smsParam = new HashMap<>();
smsParam.put("mobile",mobile);
smsParam.put("tplId", Constants.MDSMS_VERCODE_TPLID);
smsParam.put("vercode",verCode);
String message = JSON.toJSONString(smsParam);
smsProcessor.sendSmsToQueue(destination,message);
} }RandomNumberCode方法生成四位随机验证码public class RandomNumberCode {
public static String verCode(){
Random random =new Random();
return StringUtils.substring(String.valueOf(random.nextInt()*-10), 2, 6);
}
public static String randomNo(){
Random random =new Random();
return String.valueOf(Math.abs(random.nextInt()*-10));
}
}将验证码信息存到redis缓存中
springboot整合redis
添加配置文件在application.yml中redis:
host: 127.0.0.1
port: 6379
auth:
max-idle: 5
max-total: 10
max-wait-millis: 3000
新建一个类来获取变量值:@Data //该注释自动帮你完成get/set方法,在pom.xml文件引入org.projectlombok包,加速开发
/*注入*/
@Component
public class Parameters {
/*****redis config start*******/
@Value("${redis.host}")
private String redisHost;
@Value("${redis.port}")
private int redisPort;
@Value("${redis.auth}")
private String redisAuth;
@Value("${redis.max-idle}")
private int redisMaxTotal;
@Value("${redis.max-total}")
private int redisMaxIdle;
@Value("${redis.max-wait-millis}")
private int redisMaxWaitMillis;
/*****redis config end*******/
}
创建JedisPoolWrapper类@Component
@Slf4j
public class JedisPoolWrapper {
private JedisPool jedisPool = null;
@Autowired
private Parameters parameters;
@PostConstruct
public void init() throws CustomException {
try{
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxIdle(parameters.getRedisMaxIdle());
config.setMaxTotal(parameters.getRedisMaxTotal());
config.setMaxWaitMillis(parameters.getRedisMaxWaitMillis());
jedisPool = new JedisPool(config,parameters.getRedisHost(),parameters.getRedisPort(),2000);
}catch (Exception e){
log.error("Fail to initialize redis pool",e);
throw new CustomException("初始化redis失败");
}
}
public JedisPool getJedisPool(){
return jedisPool;
}
}创建一个CommonCacheUtil工具类@Component
@Slf4j
public class CommonCacheUtil {
private static final String TOKEN_PREFIX = "token.";
private static final String USER_PREFIX = "user.";
@Autowired
private JedisPoolWrapper jedisPoolWrapper;
/**
* 缓存 key value 永久
* @param key
* @param value
*/
public void cache(String key, String value) {
try {
JedisPool pool = jedisPoolWrapper.getJedisPool();
if (pool != null) {
try (Jedis Jedis = pool.getResource()) {
Jedis.select(0);//选择redis第0片区
Jedis.set(key, value);
}
}
} catch (Exception e) {
log.error("Fail to cache value", e);
}
}
/**
* 获取缓存key
* @param key
* @return
*/
4000
public String getCacheValue(String key) {
String value = null;
try {
JedisPool pool = jedisPoolWrapper.getJedisPool();
if (pool != null) {
try (Jedis Jedis = pool.getResource()) {
Jedis.select(0);
value = Jedis.get(key);
}
}
} catch (Exception e) {
log.error("Fail to get cached value", e);
}
return value;
}
/**
* 设置key value 以及过期时间
* @param key
* @param value
* @param expiry
* @return
*/
public long cacheNxExpire(String key, String value, int expiry) {
long result = 0;
try {
JedisPool pool = jedisPoolWrapper.getJedisPool();
if (pool != null) {
try (Jedis jedis = pool.getResource()) {
jedis.select(0);
result = jedis.setnx(key, value);
jedis.expire(key, expiry);
}
}
} catch (Exception e) {
log.error("Fail to cacheNx value", e);
}
return result;
}
/**
* 删除缓存key
* @param key
*/
public void delKey(String key) {
JedisPool pool = jedisPoolWrapper.getJedisPool();
if (pool != null) {
try (Jedis jedis = pool.getResource()) {
jedis.select(0);
try {
jedis.del(key);
} catch (Exception e) {
log.error("Fail to remove key from redis", e);
}
}catch (Exception e) {
log.error("Fail to remove key from redis", e);
}
}
}
/**
* 缓存手机验证码专用 限制了发送次数
* @return 1 当前验证码未过期 2 手机号超过当日验证码次数上限 3 ip超过当日验证码次数上线
*/
public int cacheForVerificationCode(String key, String verCode, String type, int second, String ip) throws Exception {
JedisPool pool = jedisPoolWrapper.getJedisPool();
if (pool != null) {
try (Jedis jedis = pool.getResource()) {
jedis.select(0);
try {
String ipKey = "ip."+ip;
if(ip==null){
return 3;
} else {
String ipSendCount = jedis.get(ipKey);
try {
if (ipSendCount != null && Integer.parseInt(ipSendCount) >= 10) {
return 3;
}
} catch (NumberFormatException e) {
log.error("Fail to process ip send count", e);
return 3;
}
long succ = jedis.setnx(key, verCode);
if (succ == 0) {
return 1;
}
String sendCount = jedis.get(key + "." + type);
try {
if (sendCount != null && Integer.parseInt(sendCount) >= 10) {
jedis.del(key);
return 2;
}
} catch (NumberFormatException e) {
log.error("Fail to process send count", e);
jedis.del(key);
return 2;
}
try {
jedis.expire(key, second);
long val = jedis.incr(key + "." + type);
if (val == 1) {
jedis.expire(key + "." + type, 86400);
}
jedis.incr(ipKey);
if (val == 1) {
jedis.expire(ipKey, 86400);
}
} catch (Exception e) {
log.error("Fail to cache data into redis", e);
}
}
} catch (Exception e) {
log.error("Fail to set vercode to redis", e);
throw e;
}
} catch (Exception e) {
log.error("Fail to cache for expiry", e);
throw new Exception("Fail to cache for expiry");
}
}
return 0;
}
}
新建一个短信接口public interface SmsSender {
void sendSms(String phone,String tplId,String params);
}实现类,依据官方demo作修改@Service("verCodeService")
@Slf4j
public class MiaoDiSmsSender implements SmsSender{
private static String operation = "/industrySMS/sendSMS";
@Override
public void sendSms(String phone,String tplId,String params){
try {
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
String timestamp = sdf.format(new Date());
String sig = MD5Util.getMD5(Constants.MDSMS_ACCOUNT_SID +Constants.MDSMS_AUTH_TOKEN +timestamp);
String url = Constants.MDSMS_REST_URL +operation;
Map<String,String> param = new HashMap<>();
param.put("accountSid",Constants.MDSMS_ACCOUNT_SID);
param.put("to",phone);
param.put("templateid",tplId);
param.put("param",params);
param.put("timestamp",timestamp);
param.put("sig",sig);
param.put("respDataType","json");
String result = HttpUtil.post(url,param);
JSONObject jsonObject = JSON.parseObject(result);
if(!jsonObject.getString("respCode").equals("00000")){
log.error("fail to send sms to "+phone+":"+params+":"+result);
}
} catch (Exception e) {
log.error("fail to send sms to "+phone+":"+params);
}
}
}整合ActiveMQ,在pom.xml文件中加入包依赖<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>新建一个消息生产者SmsProcessor类@Component("smsProcessor")
public class SmsProcessor {
@Autowired
private JmsMessagingTemplate jmsTemplate;
@Autowired
@Qualifier("verCodeService")
private SmsSender smsSender;
public void sendSmsToQueue(Destination destination, final String message){
jmsTemplate.convertAndSend(destination, message);
}
@JmsListener(destination="sms.queue")
public void doSendSmsMessage(String text){
JSONObject jsonObject = JSON.parseObject(text);
smsSender.sendSms(jsonObject.getString("mobile"),jsonObject.getString("tplId"),jsonObject.getString("vercode"));
}
}Controller代码:@RequestMapping("/sendVercode")
public ApiResult sendVercode(@RequestBody User user, HttpServletRequest request){
ApiResult resp = new ApiResult();
try {
userService.sendVercode(user.getMobile(),getIpFromRequest(request));
}catch(CustomException e){
resp.setCode(Constants.RESP_STATUS_INTERNAL_ERROR);
resp.setMessage(e.getMessage());
}
catch(CustomException e){
log.error("Fail to login",e);
resp.setCode(Constants.RESP_STATUS_INTERNAL_ERROR);
resp.setMessage("内部错误");
}
return resp;
}
User类@Data
public class User {
private Long id;
private String nickname;
private String mobile;
private String headImg;
private Byte verifyFlag;
private Byte enableFlag;
}
统一返回数据ApiResult类public class ApiResult<T> {
private int code = Constants.RESP_STATUS_OK;
private String message;
private T data;
}
自定义异常类:CustomExceptionpublic class CustomException extends Exception {
public CustomException(String message){
super(message);
}
}
常量类:Constantspublic class Constants {
/**自定义状态码 start**/
public static final int RESP_STATUS_OK = 200;
public static final int RESP_STATUS_NOAUTH = 401;
public static final int RESP_STATUS_INTERNAL_ERROR = 500;
public static final int RESP_STATUS_BADREQUEST = 400;
/**秒滴SMS start**/
public static final String MDSMS_ACCOUNT_SID = "填写自己的SID";
public static final String MDSMS_AUTH_TOKEN = "填写自己TOKEN";
public static final String MDSMS_REST_URL = "https://api.miaodiyun.com/20150822";
public static final String MDSMS_VERCODE_TPLID = "模板编号";
/**秒滴SMS end**/
public static final String REQUEST_TOKEN_KEY = "user-token";
public static final String REQUEST_VERSION_KEY = "version"
}
考虑短信接口的安全性
1.IP 根据IP来判定 超过十次 不发送验证码
手机号 同一个手机号 不能超过多少次
通过调用redis工具类中的cacheForVerificationCode方法
2.获取真正的ip+本机ip测试(ngnix负载均衡,请求分发)protected String getIpFromRequest(HttpServletRequest request) {
String ip = request.getHeader("x-forwarded-for");
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
ip = request.getHeader("Proxy-Client-IP");
}
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
ip = request.getHeader("WL-Proxy-Client-IP");
}
if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
ip = request.getRemoteAddr();
}
return ip.equals("0:0:0:0:0:0:0:1")?"127.0.0.1":ip;
}
相关文章推荐
- spring-boot整合redis作为缓存(4)——spring-boot引入Redis
- spring boot 整合 redis
- spring boot整合JMS(ActiveMQ实现)
- SpringBoot整合Redis
- 快速对接第三方接口--短信接口
- springboot+shiro+redis(集群redis版)整合教程
- spring boot 整合 redis,使用@Cacheable,@CacheEvict,@CachePut,jedisPool操作redis数据库
- java springboot与redis整合
- Spring Boot+Shiro+Redis(redisson)整合时,采用内嵌tomcat启动错误原因分析
- springboot mybatis整合redis
- SpringBoot精藏(七)SpringBoot整合redis
- spring-boot整合redis作为缓存(1)——redis的设置
- spring-boot整合redis作为缓存(3)——自定义key
- spring boot整合redis,实现shiro的CacheManager
- spring boot中spring cache 整合redis
- STS创建Spring Boot项目实战(Rest接口、数据库、用户认证、分布式Token JWT、Redis操作、日志和统一异常处理)
- SpringBoot整合mybatis、shiro、redis实现基于数据库的细粒度动态权限管理系统实例
- [增删改查] SpringBoot 整合 ElasticSearch 之 ElasticsearchRepository 的 CRUD、分页接口
- springboot整合redis