欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Satoken+Redis實(shí)現(xiàn)短信登錄、注冊(cè)、鑒權(quán)功能

 更新時(shí)間:2024年01月03日 10:25:54   作者:阿輝___  
這篇文章主要介紹了Satoken+Redis實(shí)現(xiàn)短信登錄、注冊(cè)、鑒權(quán)功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧

Springboot集成Satoken

添加依賴

注:如果你使用的是 SpringBoot 3.x,只需要將 sa-token-spring-boot-starter 修改為 sa-token-spring-boot3-starter 即可。

<!-- Sa-Token 權(quán)限認(rèn)證,在線文檔:https://sa-token.cc -->
<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-spring-boot-starter</artifactId>
    <version>1.34.0</version>
</dependency>

設(shè)置配置文件

# 端口
server.port=8081
############## Sa-Token 配置 (文檔: https://sa-token.cc) ##############
# token名稱 (同時(shí)也是cookie名稱)
sa-token.token-name=satoken
# token有效期,單位s 默認(rèn)30天, -1代表永不過(guò)期 
sa-token.timeout=2592000
# token臨時(shí)有效期 (指定時(shí)間內(nèi)無(wú)操作就視為token過(guò)期) 單位: 秒
sa-token.activity-timeout=-1
# 是否允許同一賬號(hào)并發(fā)登錄 (為true時(shí)允許一起登錄, 為false時(shí)新登錄擠掉舊登錄) 
sa-token.is-concurrent=true
# 在多人登錄同一賬號(hào)時(shí),是否共用一個(gè)token (為true時(shí)所有登錄共用一個(gè)token, 為false時(shí)每次登錄新建一個(gè)token) 
sa-token.is-share=true
# token風(fēng)格
sa-token.token-style=uuid
# 是否輸出操作日志 
sa-token.is-log=false

啟動(dòng)類

在項(xiàng)目中新建包 com.pj ,在此包內(nèi)新建主類 SaTokenDemoApplication.java,復(fù)制以下代碼:

@SpringBootApplication
public class SaTokenDemoApplication {
    public static void main(String[] args) throws JsonProcessingException {
        SpringApplication.run(SaTokenDemoApplication.class, args);
        System.out.println("啟動(dòng)成功:Sa-Token配置如下:" + SaManager.getConfig());
    }
}

登錄

用戶輸入手機(jī)號(hào),調(diào)用登錄接口,根據(jù)手機(jī)號(hào)查詢是否存在該用戶

@PostMapping("/login")
public Boolean login(@RequestBody String phone) {
  //從數(shù)據(jù)庫(kù)查詢?cè)撌謾C(jī)號(hào)的用戶
  User user = userInfoDao.selectUser(phone);
  //若不存在該用戶返回false,存在返回true
  return user == null ? false : true;
}

確認(rèn)用戶存在后就可以調(diào)用發(fā)送驗(yàn)證碼接口,再校驗(yàn)驗(yàn)證碼是否正確

/**
 * 發(fā)送驗(yàn)證碼:
 * 在redis中用hash存儲(chǔ)用戶的相關(guān)信息,用PHONE_NUM+手機(jī)號(hào)作為用戶hash的key,
 * “code”作為用戶信息hash中驗(yàn)證碼的小key,查詢r(jià)edis中用戶的驗(yàn)證碼信息,
 * "num"是驗(yàn)證次數(shù)的小key
 */
@PostMapping("/sendCaptcha")
public String sendCaptcha(String phone){
    //驗(yàn)證碼verCode
    String verCode;
    String key = "PHONE_NUM"+phone;
    //如果redis中有緩存的驗(yàn)證碼
    Object object = redisTemplate.opsForHash().get(key, "code");
    if(null != object){
        throw Error("該用戶驗(yàn)證碼已發(fā)送,且未過(guò)期,請(qǐng)輸入驗(yàn)證碼登錄或注冊(cè)!");
    }else {
        Random r = new Random(System.currentTimeMillis());
        int low = 100000;
        int high = 999999;
        //根據(jù)時(shí)間隨機(jī)生成驗(yàn)證碼verCode,將其放入redis中
        int code = (r.nextInt(high - low) + low);
        verCode = String.valueOf(code);
        redisTemplate.opsForHash().put(key,"code",verCode);
        //放入檢驗(yàn)次數(shù)num=5
        redisTemplate.opsForHash().put(key,"num",5);
        //設(shè)置過(guò)期時(shí)間
        redisTemplate.expire(key,60*5,TimeUnit.SECONDS);
    }
    try {
        //調(diào)用發(fā)送驗(yàn)證碼的接口發(fā)送驗(yàn)證碼
        String smsResult= sendMsg(phone, verCode);
    }catch (Throwable throwable){
        redisTemplate.delete(key);
        throw Error("短信發(fā)送失??!");
    }
    return "發(fā)送成功";
}

重點(diǎn)?。?!

/**
 * 校驗(yàn)驗(yàn)證碼:
 * 驗(yàn)證成功就StpUtil.login(user.getId())進(jìn)行登錄,自動(dòng)生成token并寫(xiě)入cookie中
 */
@PostMapping("/checkCaptcha")
public String checkCaptcha(String phone,String verCode){
    if(phone==null||verCode==null||phone==""||verCode==""){
        throw Errorr("請(qǐng)輸入手機(jī)及驗(yàn)證碼!");
    }
    //從redis中獲取該手機(jī)號(hào)用戶的信息
    String key = "PHONE_NUM"+phone;
    Object object = redisTemplate.opsForHash().get(key, "code");
    if(null == object){
        throw Error("未請(qǐng)求驗(yàn)證碼或驗(yàn)證碼已失效,請(qǐng)重新登錄!");
    }
    String code= object.toString();
    if(code.equals(verCode)){
        //驗(yàn)證碼比對(duì)正確,刪除redis中驗(yàn)證碼記錄
        redisTemplate.delete(key);
        //從數(shù)據(jù)庫(kù)查詢出該用戶的信息,并調(diào)用stputil進(jìn)行登錄
        User user = userService.findUser(phone);
        StpUtil.login(user.getId());
        return "登陸成功";
    }else{
        //驗(yàn)證碼比對(duì)錯(cuò)誤,校驗(yàn)次數(shù)減1
        double num = redisTemplate.opsForHash().increment(key,"num",-1);
        //若校驗(yàn)次數(shù)小于0則驗(yàn)證碼失效,不小于0則拋出驗(yàn)證碼錯(cuò)誤
        if(num < 0 ){
            redisTemplate.delete(key);
            return "未請(qǐng)求驗(yàn)證碼或驗(yàn)證碼已失效,請(qǐng)重新登錄!";
        } else {
            return "驗(yàn)證碼錯(cuò)誤!";
        }
    }
}

注銷

@PostMapping("/logout")
public Boolean logout() {
    if (!StpUtil.isLogin()) {
    throw Error("未檢測(cè)到登錄信息,請(qǐng)先登錄!");
    }
    StpUtil.logout();
    return true;
}

注冊(cè)

填入手機(jī)號(hào)后,若調(diào)用登錄接口根據(jù)手機(jī)號(hào)查詢數(shù)據(jù)庫(kù)發(fā)現(xiàn)不存在該用戶,自動(dòng)跳轉(zhuǎn)到注冊(cè)頁(yè)面

@PostMapping("/regist)
public Boolean regist(String userName,String verCode) {
    if(userName==null||verCode==null||userName==""||verCode==""){
        throw Errorr("請(qǐng)輸入用戶名或驗(yàn)證碼!");
    }
    查詢數(shù)據(jù)庫(kù)檢查該用戶名是否已經(jīng)被用;
    調(diào)用上面登錄里的校驗(yàn)用戶驗(yàn)證碼的方法;
    用戶名未被占用且驗(yàn)證碼正確,則向數(shù)據(jù)庫(kù)用戶表插入該用戶信息,得到用戶id;
    //調(diào)用stputil進(jìn)行登錄
    StpUtil.login(userId());
    return true;
}

重寫(xiě)獲取權(quán)限或角色的接口

接口的調(diào)用往往需要權(quán)限的校驗(yàn),一般的系統(tǒng)會(huì)給用戶綁定某種角色,再給此角色分配權(quán)限,設(shè)置權(quán)限碼,具有此角色或者權(quán)限碼才放行請(qǐng)求。sa-token實(shí)現(xiàn)權(quán)限需要進(jìn)行自定義擴(kuò)展,下面是獲取一個(gè)用戶權(quán)限碼集合和角色標(biāo)識(shí)集合的類:

/**
 * 自定義權(quán)限驗(yàn)證接口擴(kuò)展
 */
@Component    // 保證此類被SpringBoot掃描,完成Sa-Token的自定義權(quán)限驗(yàn)證擴(kuò)展
public class StpInterfaceImpl implements StpInterface {
    /**
     * 返回一個(gè)賬號(hào)所擁有的權(quán)限碼集合
     */
    @Override
    public List<String> getPermissionList(Object loginId, String loginType) {
        List<String> list = new ArrayList<String>();
        //1.先從redis中根據(jù)loginId取該用戶的權(quán)限,有則直接返回
        //2.若是redis中沒(méi)有,則從數(shù)據(jù)庫(kù)中查詢,再把結(jié)果添加到redis中
        return list;
        // 比如:
        // list.add("101");
        // list.add("user.add");
        // list.add("user.update");
        // list.add("user.get");
        // list.add("user.delete");
        // list.add("art.*");
    }
    /**
     * 返回一個(gè)賬號(hào)所擁有的角色標(biāo)識(shí)集合 (權(quán)限與角色可分開(kāi)校驗(yàn))
     */
    @Override
    public List<String> getRoleList(Object loginId, String loginType) {
         List<String> list = new ArrayList<String>();
        //1.先從redis中根據(jù)loginId取該用戶的角色集合,有則直接返回
        //2.若是redis中沒(méi)有,則從數(shù)據(jù)庫(kù)中查詢,再把結(jié)果添加到redis中
        return list;
        // 比如:
        // list.add("admin");
        // list.add("super-admin");
    }
}

路由攔截實(shí)現(xiàn)鑒權(quán)

在調(diào)用后臺(tái)服務(wù)時(shí),我們可以在路由時(shí)做一些攔截,例如添加登陸權(quán)限攔截、放開(kāi)一些接口白名單等。(一定要排除 登錄、注冊(cè)、發(fā)送驗(yàn)證碼等接口 的攔截)

@Configuration
public class SaTokenConfigure implements WebMvcConfigurer {
    // 注冊(cè) Sa-Token 的攔截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注冊(cè)路由攔截器,自定義認(rèn)證規(guī)則
        registry.addInterceptor(new SaInterceptor(handler -> {
            //SaRouter.match(參數(shù)一:需要攔截的路由,
                              參數(shù)二:可排除的路由,
                              參數(shù)三:用來(lái)檢驗(yàn)是否通過(guò)攔截的方法)
            // 登錄校驗(yàn) -- 用是否登錄攔截所有路由,
            // 在最下面的.excludePathPatterns中并排除登錄等接口的攔截
            SaRouter.match("/**", r -> StpUtil.checkLogin());
            // 角色校驗(yàn) -- 攔截以 admin 開(kāi)頭的路由,必須具備 admin 角色或者 super-admin 角色才可以通過(guò)認(rèn)證
            SaRouter.match("/admin/**", r -> StpUtil.checkRoleOr("admin", "super-admin"));
            // 權(quán)限校驗(yàn) -- 不同模塊校驗(yàn)不同權(quán)限
            SaRouter.match("/user/**", r -> StpUtil.checkPermission("user"));
            SaRouter.match("/admin/**", r -> StpUtil.checkPermission("admin"));
            SaRouter.match("/goods/**", r -> StpUtil.checkPermission("goods"));
            SaRouter.match("/orders/**", r -> StpUtil.checkPermission("orders"));
            SaRouter.match("/notice/**", r -> StpUtil.checkPermission("notice"));
            SaRouter.match("/comment/**", r -> StpUtil.checkPermission("comment"));
            // 甚至你可以隨意的寫(xiě)一個(gè)打印語(yǔ)句
            SaRouter.match("/**", r -> System.out.println("----啦啦啦----"));
            // 連綴寫(xiě)法
            SaRouter.match("/**").check(r -> System.out.println("----啦啦啦----"));
        })).addPathPatterns("/**")
           // 排除登錄、注冊(cè)、發(fā)送驗(yàn)證碼等接口 的攔截
           .excludePathPatterns("/user/login")
           .excludePathPatterns("/user/sendCaptcha")
           .excludePathPatterns("/user/checkCaptcha")
           .excludePathPatterns("/user/regist")
        ;
    }
}

到此這篇關(guān)于Satoken+Redis實(shí)現(xiàn)短信登錄、注冊(cè)、鑒權(quán)的文章就介紹到這了,更多相關(guān)Redis短信登錄內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • spring?boot集成redis基礎(chǔ)入門(mén)實(shí)例詳解

    spring?boot集成redis基礎(chǔ)入門(mén)實(shí)例詳解

    redis在spring?boot項(xiàng)目開(kāi)發(fā)中是常用的緩存套件,常見(jiàn)使用的是spring-boot-starter-data-redis,這篇文章主要介紹了spring?boot集成redis基礎(chǔ)入門(mén),本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-10-10
  • 如何使用Redis實(shí)現(xiàn)電商系統(tǒng)的庫(kù)存扣減

    如何使用Redis實(shí)現(xiàn)電商系統(tǒng)的庫(kù)存扣減

    在日常開(kāi)發(fā)中有很多地方都有類似扣減庫(kù)存的操作,本文主要介紹了如何使用Redis實(shí)現(xiàn)電商系統(tǒng)的庫(kù)存扣減,具有一定的參考價(jià)值,感興趣的可以了解一下
    2022-01-01
  • 淺談Redis常見(jiàn)延遲問(wèn)題定位與分析

    淺談Redis常見(jiàn)延遲問(wèn)題定位與分析

    大部分時(shí)候,redis延遲很低,但是在某些時(shí)刻,有些redis實(shí)例會(huì)出現(xiàn)很高的響應(yīng)延時(shí),本文主要介紹了淺談Redis常見(jiàn)延遲問(wèn)題定位與分析,具有一定的參考價(jià)值,感興趣的可以了解一下
    2022-06-06
  • Redis擊穿穿透雪崩產(chǎn)生原因分析及解決思路面試

    Redis擊穿穿透雪崩產(chǎn)生原因分析及解決思路面試

    這篇文章主要為大家介紹了Redis擊穿穿透雪崩產(chǎn)生原因及解決思路的面試問(wèn)題答案參考,有需要的朋友可以借鑒參考下,希望能夠有所幫助祝大家多多進(jìn)步
    2022-03-03
  • Redis RDB與AOF持久化方式詳細(xì)講解

    Redis RDB與AOF持久化方式詳細(xì)講解

    Redis是基于內(nèi)存的數(shù)據(jù)結(jié)構(gòu)服務(wù)器,保存了大量的鍵值對(duì)數(shù)據(jù),所以持久化到磁盤(pán)是非常必要的,Redis提供了兩種持久化的方式,分別是RDB和AOF。下面我們看下這兩種持久化方式的具體實(shí)現(xiàn)原理
    2022-11-11
  • Redis教程(十一):虛擬內(nèi)存介紹

    Redis教程(十一):虛擬內(nèi)存介紹

    這篇文章主要介紹了Redis教程(十一):虛擬內(nèi)存介紹,本文講解了虛擬內(nèi)存簡(jiǎn)介、應(yīng)用場(chǎng)景和配置方法等內(nèi)容,需要的朋友可以參考下
    2015-04-04
  • Windows設(shè)置Redis為開(kāi)機(jī)自啟動(dòng)的流程步驟

    Windows設(shè)置Redis為開(kāi)機(jī)自啟動(dòng)的流程步驟

    Redis作為當(dāng)前最常用的當(dāng)前緩存技術(shù),基本上Web應(yīng)用中都有使用,所以,每次我們?cè)诒镜貑?dòng)項(xiàng)目前,都必須將Redis服務(wù)端啟動(dòng),但是,每次都要去啟動(dòng)Redis就很麻煩,本文主要就是介紹Windows系統(tǒng)如何配置開(kāi)機(jī)啟動(dòng)Redis,需要的朋友可以參考下
    2024-05-05
  • Redis的使用模式之計(jì)數(shù)器模式實(shí)例

    Redis的使用模式之計(jì)數(shù)器模式實(shí)例

    這篇文章主要介紹了Redis的使用模式之計(jì)數(shù)器模式實(shí)例,本文講解了匯總計(jì)數(shù)器、按時(shí)間匯總的計(jì)數(shù)器、速度控制、使用 Hash 數(shù)據(jù)類型維護(hù)大量計(jì)數(shù)器等內(nèi)容,需要的朋友可以參考下
    2015-03-03
  • Redis刪除過(guò)期key策略詳解

    Redis刪除過(guò)期key策略詳解

    Redis是一款高性能的開(kāi)源內(nèi)存數(shù)據(jù)庫(kù),廣泛應(yīng)用于緩存、消息隊(duì)列、實(shí)時(shí)分析等場(chǎng)景,在Redis中,我們經(jīng)常需要?jiǎng)h除過(guò)期的key,以釋放內(nèi)存空間并保持?jǐn)?shù)據(jù)的有效性,本文將為您詳細(xì)介紹Redis的過(guò)期key刪除策略,幫助您更好地管理和優(yōu)化Redis數(shù)據(jù)庫(kù)
    2023-10-10
  • CentOS8.4安裝Redis6.2.6的詳細(xì)過(guò)程

    CentOS8.4安裝Redis6.2.6的詳細(xì)過(guò)程

    本文給大家介紹CentOS8.4安裝Redis6.2.6的詳細(xì)過(guò)程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2021-11-11

最新評(píng)論