目錄
一、短信發(fā)送
1.1 阿里云短信服務(wù)
1.1.1 設(shè)置短信簽名
1.1.2 模板管理
1.1.3 設(shè)置AccessKey
1.2 短信發(fā)送——代碼開發(fā)
1.2.1 導(dǎo)入maven坐標(biāo)
1.2.2 調(diào)用API
1.2? 手機(jī)驗(yàn)證碼登錄
1.2.1 用戶數(shù)據(jù)庫(kù)表
1.2.2? 修改過濾器
1.2.3? ?隨機(jī)生成驗(yàn)證碼的工具類
1.2.4?手機(jī)驗(yàn)證碼登錄-- 發(fā)送驗(yàn)證碼
1.2.5?手機(jī)驗(yàn)證碼登錄-- 驗(yàn)證驗(yàn)證碼
一、短信發(fā)送
1.1 阿里云短信服務(wù)
短信服務(wù)_企業(yè)短信營(yíng)銷推廣_驗(yàn)證碼通知-阿里云
也可以在下面這個(gè)地方查看短信服務(wù)?
1.1.1 設(shè)置短信簽名
短信簽名就是短信發(fā)送者的署名,表示發(fā)送方的身份
1.1.2 模板管理
?申請(qǐng)下來(lái)之后可以點(diǎn)擊詳情進(jìn)行查看
? ? ?其中模板CODE是自動(dòng)生成的,不用管,重點(diǎn)是模板的內(nèi)容
1.1.3 設(shè)置AccessKey
?
創(chuàng)建新的用戶
勾選上之后,我們?cè)诰幊檀a中就能使用
?
當(dāng)我們創(chuàng)建用戶成功后,就生成了一對(duì)AccessKey,即AccessKey ID(用戶名) 與AccessKey Secret(密碼)
很多人在這里的時(shí)候不小心沒截圖或者沒保存就關(guān)了,丟失了AccessKey,但是不要緊,還可以再次創(chuàng)建
還有就是如果別人知道了我們的AccessKey,那別人使用的時(shí)候會(huì)就花我們的錢。我們也可以把泄露的AccessKey禁用
之后再新增授權(quán)。這次授權(quán)的意思就是僅僅授予有關(guān)短信服務(wù)的,即是我們泄露了,別人也只能操作短信服務(wù),對(duì)我們的影響很小。
1.2 短信發(fā)送——代碼開發(fā)
參照官方文檔即可
新手指引_短信服務(wù)-阿里云幫助中心
1.2.1 導(dǎo)入maven坐標(biāo)
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.5.16</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
<version>2.1.0</version>
</dependency>
1.2.2 調(diào)用API
/**
* 短信發(fā)送工具類
*/
public class SMSUtils {
/**
* 發(fā)送短信
* @param signName 簽名
* @param templateCode 模板
* @param phoneNumbers 手機(jī)號(hào)
* @param param 參數(shù)
*/
public static void sendMessage(String signName, String templateCode,String phoneNumbers,String param){
DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", "LTAI5tHRxs2FeCu5JcJTGbm2", "v0H4PaJpXSwNr6XChtlVYAgmQWgKRA");
IAcsClient client = new DefaultAcsClient(profile);
SendSmsRequest request = new SendSmsRequest();
request.setSysRegionId("cn-hangzhou");
// 要發(fā)送給那個(gè)人的電話號(hào)碼
request.setPhoneNumbers(phoneNumbers);
// 我們?cè)诎⒗镌圃O(shè)置的簽名
request.setSignName(signName);
// 我們?cè)诎⒗镌圃O(shè)置的模板
request.setTemplateCode(templateCode);
// 在設(shè)置模板的時(shí)候有一個(gè)占位符
request.setTemplateParam("{\"code\":\""+param+"\"}");
// request.setPhoneNumbers("1368846****");//接收短信的手機(jī)號(hào)碼
// request.setSignName("阿里云");//短信簽名名稱
// request.setTemplateCode("SMS_20933****");//短信模板CODE
// request.setTemplateParam("張三");//短信模板變量對(duì)應(yīng)的實(shí)際值
try {
SendSmsResponse response = client.getAcsResponse(request);
System.out.println("短信發(fā)送成功");
}catch (ClientException e) {
e.printStackTrace();
}
}
}
1.2? 手機(jī)驗(yàn)證碼登錄
- 方便、快捷、無(wú)需注冊(cè)、直接登陸
- 使用短信驗(yàn)證碼作為登錄憑證,無(wú)序記憶密碼
- 安全
登錄流程:? 輸入手機(jī)號(hào)? ->? 獲取驗(yàn)證碼? ->? 輸入驗(yàn)證碼? ->? 點(diǎn)擊登錄? ->? 登陸成功
注意: 通過手機(jī)驗(yàn)證碼登錄,手機(jī)號(hào)是區(qū)分不同用戶的標(biāo)識(shí)
1.2.1 用戶數(shù)據(jù)庫(kù)表
因?yàn)槭峭ㄟ^手機(jī)和驗(yàn)證碼登錄的,所以沒有用戶名和密碼字段
1.2.2? 修改過濾器
?在寫代碼之前記得要在過濾器中定義不需要處理的請(qǐng)求路徑/user/sendMsg和/user/login
?然后訪問路徑:?http://localhost:8080/front/page/login.html
/**
* 檢查用戶是否已經(jīng)完成登錄
* 過濾器與攔截器的區(qū)別:Filter對(duì)所有訪問進(jìn)行增強(qiáng)(在Tomcat服務(wù)器進(jìn)行配置),Interceptor僅針對(duì)SpringMVC的訪問進(jìn)行增強(qiáng)
*/
@Slf4j
@WebFilter(filterName = "loginCheckFilter", urlPatterns = "/*") //urlPatterns指定攔截哪些路徑
public class LoginCheckFilter implements Filter {
// 此對(duì)象的作用:路徑匹配器, 匹配路徑時(shí)支持通配符
public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// servletRequest向下強(qiáng)制類型轉(zhuǎn)換
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
//1. 獲取本次請(qǐng)求的URI( URI:請(qǐng)求的資源路徑)
String requestURI = request.getRequestURI();
log.info("攔截到請(qǐng)求:{}", request.getRequestURI());
// 定義不用處理的請(qǐng)求路徑
String[] urls = new String[]{
"/employee/login",
"/employee/logout",
"/backend/**",
"/front/**",
"/common/**",
"/user/sendMsg",
"/user/login"
};
//2. 判斷本次請(qǐng)求是否需要處理(因?yàn)橛行┱?qǐng)求并不需要用戶登錄)
boolean check = check(requestURI, urls);
//3.如果不需要處理,則直接放行
if (check) {
log.info("本次請(qǐng)求{}不需要處理", request.getRequestURI());
filterChain.doFilter(request, response);
return;
}
//4-1.判斷登錄狀態(tài),如果已登錄,則直接放行.從session中獲取用戶,如果獲取到說明已經(jīng)登錄
if (request.getSession().getAttribute("employee") != null) {
log.info("用戶已登錄,用戶id為{}", request.getSession().getAttribute("employee"));
Long empId = (Long) request.getSession().getAttribute("employee");
BaseContext.setCurrentId(empId);
filterChain.doFilter(request, response);
return;
}
//4-2.判斷登錄狀態(tài),如果已登錄,則直接放行.從session中獲取用戶,如果獲取到說明已經(jīng)登錄
if (request.getSession().getAttribute("user") != null) {
log.info("用戶已登錄,用戶id為{}", request.getSession().getAttribute("user"));
Long userId = (Long) request.getSession().getAttribute("user");
BaseContext.setCurrentId(userId);
filterChain.doFilter(request, response);
return;
}
//5.如果未登錄則返回未登錄結(jié)果
log.info("資源路徑路徑:{},用戶未登錄{}", request.getRequestURI(), request.getSession().getAttribute("employee"));
// 通過輸出流的方式向客戶端響應(yīng)數(shù)據(jù) (為什么要返回這個(gè)NOTLOGIN? 因?yàn)榍岸诵枰@個(gè)來(lái)進(jìn)行判定是否登錄)
response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));
// filterChain.doFilter(request, response); 加上這個(gè)就無(wú)法實(shí)現(xiàn)
}
/**
* 檢查本次請(qǐng)求是否需要放行
*
* @param requestURI 請(qǐng)求的資源路徑
* @param urls 放過的路徑
* @return true 放行
*/
public boolean check(String requestURI, String[] urls) {
for (String url : urls) {
boolean match = PATH_MATCHER.match(url, requestURI);
if (match) {
// 放行
return true;
}
}
return false;
}
}
1.2.3? ?隨機(jī)生成驗(yàn)證碼的工具類
/**
* 隨機(jī)生成驗(yàn)證碼工具類
*/
public class ValidateCodeUtils {
/**
* 隨機(jī)生成驗(yàn)證碼
* @param length 長(zhǎng)度為4位或者6位
* @return
*/
public static Integer generateValidateCode(int length){
Integer code =null;
// 長(zhǎng)度為4
if(length == 4){
code = new Random().nextInt(9999);//生成隨機(jī)數(shù),最大為9999
if(code < 1000){
code = code + 1000;//保證隨機(jī)數(shù)為4位數(shù)字
}
// 長(zhǎng)度為6
}else if(length == 6){
code = new Random().nextInt(999999);//生成隨機(jī)數(shù),最大為999999
if(code < 100000){
code = code + 100000;//保證隨機(jī)數(shù)為6位數(shù)字
}
// 其他情況
}else{
throw new RuntimeException("只能生成4位或6位數(shù)字驗(yàn)證碼");
}
return code;
}
/**
* 隨機(jī)生成指定長(zhǎng)度字符串驗(yàn)證碼
* @param length 長(zhǎng)度
* @return
*/
public static String generateValidateCode4String(int length){
Random rdm = new Random();
String hash1 = Integer.toHexString(rdm.nextInt());
String capstr = hash1.substring(0, length);
return capstr;
}
}
1.2.4?手機(jī)驗(yàn)證碼登錄-- 發(fā)送驗(yàn)證碼
兩次ajax請(qǐng)求:
? ?1. 登錄頁(yè)面輸入手機(jī)號(hào),點(diǎn)擊【獲取驗(yàn)證碼】按鈕,頁(yè)面發(fā)送ajax請(qǐng)求,在服務(wù)端調(diào)用短信服務(wù)API給指定手機(jī)號(hào)發(fā)送驗(yàn)證碼短信文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-421301.html
? ?2. 在登錄頁(yè)面輸入驗(yàn)證碼,點(diǎn)擊【登錄】按鈕,發(fā)送ajax請(qǐng)求,在服務(wù)端處理登錄請(qǐng)求文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-421301.html
@PostMapping("/sendMsg")
public R<String> sendMsg(@RequestBody User user, HttpSession session){
// 1.獲取手機(jī)號(hào)
String phone = user.getPhone();
if(StringUtils.isEmpty(phone)){
return R.error("短信發(fā)送失敗");
}
// 2.隨機(jī)生成四位驗(yàn)證碼
String code = ValidateCodeUtils.generateValidateCode(4).toString();
// 3.調(diào)用阿里云提供的短信服務(wù)
SMSUtils.sendMessage("張靖奇","",phone,code);
// 4.需要將生成的驗(yàn)證碼保存到session中
session.setAttribute(phone,code);
return R.success("驗(yàn)證碼短信發(fā)送成功");
}
1.2.5?手機(jī)驗(yàn)證碼登錄-- 驗(yàn)證驗(yàn)證碼
// 其實(shí)傳過來(lái)的phone:xxxx,code:xxx 也可以用map集合接收
@PostMapping("/login")
public R<User> login(@RequestBody Map map, HttpSession session) {
log.info(map.toString());
// 1. 獲取手機(jī)號(hào)
String phone = map.get("phone").toString();
// 2. 獲取驗(yàn)證碼
String code = map.get("code").toString();
// 3. 從Session中獲取保存的驗(yàn)證碼
Object codeInSession = session.getAttribute(phone);
// 4. 進(jìn)行驗(yàn)證碼比對(duì)(頁(yè)面提交的驗(yàn)證碼和Session中保存的驗(yàn)證碼比對(duì))
if (codeInSession != null && codeInSession.equals(code)) {
// 5.對(duì)比成功,說明登錄成功
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(User::getPhone,phone);
User user = userService.getOne(queryWrapper);
if (user==null){
// 6. 如果新用戶,自動(dòng)注冊(cè)
user = new User();
user.setPhone(phone);
user.setStatus(1);
userService.save(user);
}
session.setAttribute("user",user.getId());
return R.success(user);
}
return R.error("登錄失敗");
}
到了這里,關(guān)于SpringBoot——短信發(fā)送、手機(jī)驗(yàn)證碼登錄的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!