亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

如何基于Session實(shí)現(xiàn)短信登錄功能

 更新時(shí)間:2022年10月31日 10:12:08   作者:我愛布朗熊  
對(duì)比起Cookie,Session是存儲(chǔ)在服務(wù)器端的會(huì)話,相對(duì)安全,并且不像Cookie那樣有存儲(chǔ)長(zhǎng)度限制,下面這篇文章主要給大家介紹了關(guān)于如何基于Session實(shí)現(xiàn)短信登錄功能的相關(guān)資料,需要的朋友可以參考下

一、基于Session實(shí)現(xiàn)登錄

1.1 業(yè)務(wù)流程圖

二、發(fā)送短信驗(yàn)證碼

2.1 發(fā)送短信請(qǐng)求方式及參數(shù)說明

這個(gè)地方為什么需要session?  因?yàn)槲覀冃枰羊?yàn)證碼保存在session當(dāng)中

     /**
     * 發(fā)送手機(jī)驗(yàn)證碼
     */
    @PostMapping("code")
    public Result sendCode(@RequestParam("phone") String phone, HttpSession session) {
        // TODO 發(fā)送短信驗(yàn)證碼并保存驗(yàn)證碼
//        return Result.fail("功能未完成");
        return userService.sendCode(phone,session);
    }

2.2 業(yè)務(wù)層代碼模擬發(fā)送短信

    @Override
    public Result sendCode(String phone, HttpSession session) {
//      1.校驗(yàn)手機(jī)號(hào)
        if(RegexUtils.isPhoneInvalid(phone)){
//              說明:RegexUtils使我們封裝的一個(gè)類   isCodeInvalid是里面的靜態(tài)方法,在這個(gè)靜態(tài)方法里面又調(diào)用了另外一個(gè)靜態(tài)方法得以實(shí)現(xiàn)
//      2.如果不符合,返回錯(cuò)誤信息
            return Result.fail("手機(jī)號(hào)格式錯(cuò)誤");
        }
 
//      3.符合,生成驗(yàn)證碼    6代表生成的驗(yàn)證碼的長(zhǎng)度  RandomUtil使用這個(gè)工具類生成
        String code =  RandomUtil.randomNumbers(6);
//      4.保存驗(yàn)證碼到session       key必須是一個(gè)字符串,value是一個(gè)對(duì)象
        session.setAttribute("code",code);
//      5.發(fā)送驗(yàn)證碼
//        實(shí)現(xiàn)起來比較麻煩 我們使用日志假裝發(fā)送
        log.debug("發(fā)送短信驗(yàn)證碼成功,驗(yàn)證碼:"+code);
        return Result.ok();
    }
}

三、登錄功能  

3.1  短信驗(yàn)證的請(qǐng)求方式及路徑

    /**
     * 登錄功能
     * @param loginForm 登錄參數(shù),包含手機(jī)號(hào)、驗(yàn)證碼;或者手機(jī)號(hào)、密碼
     */
    @PostMapping("/login")
    public Result login(@RequestBody LoginFormDTO loginForm, HttpSession session){
        // TODO 實(shí)現(xiàn)登錄功能
        return userService.login(loginForm,session);
    }

3.2  業(yè)務(wù)層代碼實(shí)現(xiàn)用戶登錄

流程圖:

代碼:

 
    /**
     * 實(shí)現(xiàn)用戶登錄
     * @param loginForm  登錄的參數(shù)
     * @param session
     * @return
     */
    @Override
    public Result login(LoginFormDTO loginForm, HttpSession session) {
//      1.校驗(yàn)手機(jī)號(hào)
        if(RegexUtils.isPhoneInvalid(loginForm.getPhone())){
//              說明:RegexUtils使我們封裝的一個(gè)類   isCodeInvalid是里面的靜態(tài)方法,在這個(gè)靜態(tài)方法里面又調(diào)用了另外一個(gè)靜態(tài)方法得以實(shí)現(xiàn)
//          1.2.如果不符合,返回錯(cuò)誤信息
            return Result.fail("手機(jī)號(hào)格式錯(cuò)誤");
        }
//      2.校驗(yàn)驗(yàn)證碼
//           2.1 得到code 這個(gè)值是真實(shí)的code
        Object cacheCode = session.getAttribute("code");
//           2.2 獲取用戶輸入的code
        String code = loginForm.getCode();
        if(cacheCode ==null || !cacheCode.toString().equals(code)){
//      3.不一致,報(bào)錯(cuò)
            return Result.fail("驗(yàn)證碼錯(cuò)誤");
        }
 
//      4.一致,根據(jù)手機(jī)號(hào)查詢用戶   .one()代表查詢一個(gè)  list()代表著查詢多個(gè)
        User user =query().eq("phone",loginForm.getPhone()).one();
 
//      5.判斷用戶是否存在
        if(user ==null){
//      6.不存在,創(chuàng)建新用戶并保存
             user = createUserWithPhone(loginForm.getPhone());
        }
 
//      7.保存用戶信息到session中
        session.setAttribute("user",user);
        return Result.ok();
    }
 
    private User createUserWithPhone(String phone) {
//      1.創(chuàng)建用戶
        User user = new User();
        user.setPhone(phone);
//       USER_NICK_NAME_PREFIX其實(shí)就是 "user_",這樣寫更有逼格
        user.setNickName(USER_NICK_NAME_PREFIX+RandomUtil.randomString(10));
//        保存用戶
        save(user);
 
        return user;
    }

3.3 攔截器——登錄驗(yàn)證功能

// HandlerInterceptor 這是一個(gè)攔截器
public class LoginInterceptor implements HandlerInterceptor {
//  前置攔截   在進(jìn)入controller之前我們進(jìn)行登錄校驗(yàn)
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//      1.獲取session
        HttpSession session  =request.getSession();
//      2.獲取session中的用戶
        Object user = session.getAttribute("user");
//      3.判斷用戶是否存在
        if(user == null){
            // 4.不存在,攔截
            response.setStatus(401);  //返回401狀態(tài)碼
            return false;
        }
//      5.存在,保存用戶信息到ThreadLocal  保存在當(dāng)前線程里面的
        UserHolder.saveUser((User)user);
//      6.放行
        return true;
    }
//  在controller執(zhí)行之后攔截  這個(gè)我們?cè)谶@里不需要
//    @Override
//    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
//        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
//    }
 
//  渲染之后,返回給用戶之前   用戶業(yè)務(wù)執(zhí)行完畢我們要銷毀維護(hù)信息,避免泄露
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
//      移除用戶
        UserHolder.removeUser();
    }
}
public class UserHolder {
    private static final ThreadLocal<User> tl = new ThreadLocal<>();
 
    public static void saveUser(User user){
        tl.set(user);
    }
 
    public static User getUser(){
        return tl.get();
    }
 
    public static void removeUser(){
        tl.remove();
    }
}
@Configuration
public class MvcConfig implements WebMvcConfigurer {
 
//  攔截器的注冊(cè)器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginInterceptor())
                .excludePathPatterns(
                        "/user/code",
                        "/user/login",
                        "/shop/**",
                        "/blog/hot",
                        "/shop-type/**",
                        "upload/**",
                        "voucher/**"
                );
    }
}
    @GetMapping("/me")
    public Result me(){
        // TODO 獲取當(dāng)前登錄的用戶并返回
//        直接取就可以了
       User user=  UserHolder.getUser();
       
        return Result.ok(user);
    }

三、隱藏用戶敏感信息

如下圖所示,服務(wù)器返回的信息有點(diǎn)多,我們?yōu)榱吮Wo(hù)用戶的信息,我們需要隱藏部分的內(nèi)容

所以一開始我們存入session的信息就不應(yīng)該是完整的信息,這樣才能降低服務(wù)器的壓力

UserServiceImpl中的login方法

//      7.保存用戶信息到session中   \
//         BeanUtil.copyProperties(user, UserDTO.class))  會(huì)自動(dòng)的將user中的屬性拷貝到UserDTO當(dāng)中而且也創(chuàng)建出一個(gè)UserDTO對(duì)象
        session.setAttribute("user", BeanUtil.copyProperties(user, UserDTO.class));

取的時(shí)候我們也應(yīng)該做出變化

LoginInterceptor類

//      5.存在,保存用戶信息到ThreadLocal  保存在當(dāng)前線程里面的
        UserHolder.saveUser((UserDTO)user);

此時(shí)我們?cè)俚卿洸樵冃畔ⅲ瓦€剩下三個(gè)字段了

四、session共享問題

多臺(tái)Tomcat并不共享session存儲(chǔ)空間,當(dāng)請(qǐng)求切換到不同的Tomcat服務(wù)導(dǎo)致數(shù)據(jù)丟失的問題

所以這個(gè)方案就被pass了

session的替代方案應(yīng)該滿足:

數(shù)據(jù)共享內(nèi)存存儲(chǔ)key、value結(jié)構(gòu)

所以我們選擇Redis

任何一臺(tái)Tomcat都能訪問到Redis,這樣就能實(shí)現(xiàn)數(shù)據(jù)共享

總結(jié)

到此這篇關(guān)于如何基于Session實(shí)現(xiàn)短信登錄功能的文章就介紹到這了,更多相關(guān)Session短信登錄內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • redis中事務(wù)機(jī)制及樂觀鎖的實(shí)現(xiàn)

    redis中事務(wù)機(jī)制及樂觀鎖的實(shí)現(xiàn)

    這篇文章主要介紹了redis中事務(wù)機(jī)制及樂觀鎖的相關(guān)內(nèi)容,通過事務(wù)的執(zhí)行分析Redis樂觀鎖,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-10-10
  • 一文詳解Redis中的持久化

    一文詳解Redis中的持久化

    這篇文章主要介紹了一文詳解Redis中的持久化,持久化功能有效地避免因進(jìn)程退出造成的數(shù)據(jù)丟失問題,當(dāng)下次重啟時(shí)利用之前持久化的文件即可實(shí)現(xiàn)數(shù)據(jù)恢復(fù)
    2022-09-09
  • Redis權(quán)限和訪問控制的實(shí)現(xiàn)示例

    Redis權(quán)限和訪問控制的實(shí)現(xiàn)示例

    Redis提供了一些機(jī)制來保護(hù)敏感數(shù)據(jù)和限制對(duì)Redis服務(wù)器的訪問,本文主要介紹了Redis權(quán)限和訪問控制的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-12-12
  • Redis實(shí)戰(zhàn)之商城購(gòu)物車功能的實(shí)現(xiàn)代碼

    Redis實(shí)戰(zhàn)之商城購(gòu)物車功能的實(shí)現(xiàn)代碼

    這篇文章主要介紹了Redis實(shí)戰(zhàn)之商城購(gòu)物車功能的實(shí)現(xiàn)代碼,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-02-02
  • 基于Redis延遲隊(duì)列的實(shí)現(xiàn)代碼

    基于Redis延遲隊(duì)列的實(shí)現(xiàn)代碼

    在生活中很多時(shí)候都會(huì)用到延遲隊(duì)列,本文基于Redis延遲隊(duì)列的實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-05-05
  • Redis數(shù)據(jù)結(jié)構(gòu)之intset整數(shù)集合使用學(xué)習(xí)

    Redis數(shù)據(jù)結(jié)構(gòu)之intset整數(shù)集合使用學(xué)習(xí)

    這篇文章主要為大家介紹了Redis數(shù)據(jù)結(jié)構(gòu)之整數(shù)集合使用學(xué)習(xí),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • redis配置standAlone版的jedisPool示例

    redis配置standAlone版的jedisPool示例

    這篇文章主要為大家介紹了redis配置standAlone版的jedisPool示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-07-07
  • kubernetes環(huán)境部署單節(jié)點(diǎn)redis數(shù)據(jù)庫(kù)的方法

    kubernetes環(huán)境部署單節(jié)點(diǎn)redis數(shù)據(jù)庫(kù)的方法

    這篇文章主要介紹了kubernetes環(huán)境部署單節(jié)點(diǎn)redis數(shù)據(jù)庫(kù)的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-01-01
  • redis如何更新升級(jí)版本

    redis如何更新升級(jí)版本

    這篇文章主要介紹了redis如何更新升級(jí)版本問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • Redis中的3種特殊數(shù)據(jù)結(jié)構(gòu)詳解

    Redis中的3種特殊數(shù)據(jù)結(jié)構(gòu)詳解

    在本文中,我們對(duì)三種特殊的數(shù)據(jù)類型進(jìn)行了介紹,它們分別是geospatial(地理空間數(shù)據(jù)類型)、HyperLogLogs和Bitmaps(位圖),這些數(shù)據(jù)類型在不同的領(lǐng)域和應(yīng)用中發(fā)揮著重要作用,并且具有各自獨(dú)特的特性和用途,對(duì)Redis特殊數(shù)據(jù)結(jié)構(gòu)相關(guān)知識(shí)感興趣的朋友一起看看吧
    2024-02-02

最新評(píng)論