


Comment implémenter la connexion SMS dans l'application de session partagée Redis
Jun 03, 2023 pm 03:11 PM
1. Implémenter la connexion par SMS en fonction de la session
1.1 Organigramme de connexion par SMS
1.2 Implémenter l'envoi du code de vérification par SMS
Instructions de demande frontale?:
|
Instructions |
---|---|
Méthode de demande | POST |
Chemin de la demande | /utilisateur/code |
Paramètres de la demande | téléphone (numéro de téléphone) |
Valeur de retour | Aucun |
Backend Implémentation de l'interface:
@Slf4j @Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService { @Override public Result sendCode(String phone, HttpSession session) { // 1. 校驗手機號 if(RegexUtils.isPhoneInvalid(phone)){ // 2. 如果不符合,返回錯誤信息 return Result.fail("手機號格式錯誤!"); } // 3. 符合,生成驗證碼(設置生成6位) String code = RandomUtil.randomNumbers(6); // 4. 保存驗證碼到 session session.setAttribute("code", code); // 5. 發(fā)送驗證碼(這里并未實現(xiàn),通過日志記錄) log.debug("發(fā)送短信驗證碼成功,驗證碼:{}", code); // 返回 ok return Result.ok(); } }
1.3 Implémenter la connexion et l'enregistrement du code de vérification SMS
Instructions de demande frontale
Instructions | |
---|---|
Request method | POST |
Request chemin | /utilisateur/ login |
Paramètres de demande | téléphone (numéro de téléphone); code (code de vérification) |
Valeur de retour | Aucun |
Implémentation de l'interface backend:
@Slf4j @Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService { @Override public Result login(LoginFormDTO loginForm, HttpSession session) { // 1. 校驗手機號 String phone = loginForm.getPhone(); if(RegexUtils.isPhoneInvalid(phone)){ // 不一致,返回錯誤信息 return Result.fail("手機號格式錯誤!"); } // 2. 校驗驗證碼 String cacheCode = (String) session.getAttribute("code"); String code = loginForm.getCode(); if(cacheCode == null || !cacheCode.equals(cacheCode)){ // 不一致,返回錯誤信息 return Result.fail("驗證碼錯誤!"); } // 4. 一致,根據(jù)手機號查詢用戶(這里使用的 mybatis-plus) User user = query().eq("phone", phone).one(); // 5. 判斷用戶是否存在 if(user == null){ // 6. 不存在,創(chuàng)建新用戶并保存 user = createUserWithPhone(phone); } // 7. 保存用戶信息到 session 中(通過 BeanUtil.copyProperties 方法將 user 中的信息過濾到 UserDTO 上,即用來隱藏部分信息) session.setAttribute("user", BeanUtil.copyProperties(user, UserDTO.class)); return Result.ok(); } private User createUserWithPhone(String phone) { // 1. 創(chuàng)建用戶 User user = new User(); user.setPhone(phone); user.setNickName("user_" + RandomUtil.randomString(10)); // 2. 保存用戶(這里使用 mybatis-plus) save(user); return user; } }
1.4 Implémenter l'intercepteur de vérification de connexion
Log en vérification Implémentation de l'intercepteur?:
public class LoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 1. 獲取 session HttpSession session = request.getSession(); // 2. 獲取 session 中的用戶 UserDTO user = (UserDTO) session.getAttribute("user"); // 3. 判斷用戶是否存在 if(user == null){ // 4. 不存在,攔截,返回 401 未授權(quán) response.setStatus(401); return false; } // 5. 存在,保存用戶信息到 ThreadLocal UserHolder.saveUser(user); // 6. 放行 return true; } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // 移除用戶,避免內(nèi)存泄露 UserHolder.removeUser(); } }
Implémentation de la classe UserHolder?: Cette classe définit un ThreadLocal
public class UserHolder { private static final ThreadLocal<UserDTO> tl = new ThreadLocal<>(); public static void saveUser(UserDTO user){ tl.set(user); } public static UserDTO getUser(){ return tl.get(); } public static void removeUser(){ tl.remove(); } }
Intercepteur de configuration statique?:
@Configuration public class MvcConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor()) .excludePathPatterns( "/user/login", "/user/code" ); } }
Description de la requête frontale?:
Instructions | |
---|---|
Méthode de demande | POST |
Chemin de la requête | /user/me |
Paramètres de la requête | Aucun |
Valeur de retour | Aucun |
Implémentation de l'interface backend?:
@Slf4j @Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService { @Override public Result me() { UserDTO user = UserHolder.getUser(); return Result.ok(user); } }
2. Problème de partage de session groupée
Session problème de partage?:
Plusieurs Tomcats ne partagent pas l'espace de stockage de session. Lorsque la requête est basculée vers différents services Tomcat, cela entra?nera une perte de données.
Les alternatives de session doivent remplir les conditions suivantes?:
Partage de données (différents Tomcats peuvent accéder aux données dans Redis)
Stockage en mémoire (Redis est stocké via la mémoire)
clé, structure de valeur (Redis est un structure clé-valeur)
3. Pour réaliser la connexion de session partagée
3.1 Redis pour implémenter l'organigramme de connexion de session
3.2 Réalisation de l'envoi du code de vérification par SMS
front-end description de la demande?:
Description | |
---|---|
Méthode de demande | POST |
Chemin de la demande | /utilisateur/code |
Paramètre de la demande | téléphone (numéro de téléphone) |
valeur de retour | Aucun |
Implémentation de l'interface back-end?:
@Slf4j @Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService { @Resource private StringRedisTemplate stringRedisTemplate; @Override public Result sendCode(String phone, HttpSession session) { // 1. 校驗手機號 if (RegexUtils.isPhoneInvalid(phone)) { // 2. 如果不符合,返回錯誤信息 return Result.fail("手機號格式錯誤!"); } // 3. 符合,生成驗證碼(設置生成6位) String code = RandomUtil.randomNumbers(6); // 4. 保存驗證碼到 Redis(以手機號為 key,設置有效期為 2min) stringRedisTemplate.opsForValue().set("login:code:" + phone, code, 2, TimeUnit.MINUTES); // 5. 發(fā)送驗證碼(這里并未實現(xiàn),通過日志記錄) log.debug("發(fā)送短信驗證碼成功,驗證碼:{}", code); // 返回 ok return Result.ok(); } }
3.3 Implémenter la connexion et l'enregistrement du code de vérification par SMS
Instructions de demande frontale?:
Instructions | |
---|---|
Méthode de demande | POST |
Chemin de la demande | /utilisateur/connexion |
Paramètres de la demande | téléphone (numéro de téléphone)?; code (code de vérification) |
Valeur de retour | Aucun |
Interface back-end implémentation?:
@Slf4j @Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService { @Override public Result login(LoginFormDTO loginForm, HttpSession session) { // 1. 校驗手機號 String phone = loginForm.getPhone(); if(RegexUtils.isPhoneInvalid(phone)){ // 不一致,返回錯誤信息 return Result.fail("手機號格式錯誤!"); } // 2. 校驗驗證碼 String cacheCode = (String) session.getAttribute("code"); String code = loginForm.getCode(); if(cacheCode == null || !cacheCode.equals(cacheCode)){ // 不一致,返回錯誤信息 return Result.fail("驗證碼錯誤!"); } // 4. 一致,根據(jù)手機號查詢用戶(這里使用的 mybatis-plus) User user = query().eq("phone", phone).one(); // 5. 判斷用戶是否存在 if(user == null){ // 6. 不存在,創(chuàng)建新用戶并保存 user = createUserWithPhone(phone); } // 7. 保存用戶信息到 session 中(通過 BeanUtil.copyProperties 方法將 user 中的信息過濾到 UserDTO 上,即用來隱藏部分信息) session.setAttribute("user", BeanUtil.copyProperties(user, UserDTO.class)); return Result.ok(); } private User createUserWithPhone(String phone) { // 1. 創(chuàng)建用戶 User user = new User(); user.setPhone(phone); user.setNickName("user_" + RandomUtil.randomString(10)); // 2. 保存用戶(這里使用 mybatis-plus) save(user); return user; } }
3.4 Implémenter l'intercepteur de vérification de connexion
L'intercepteur d'origine est divisé en deux intercepteurs.Le premier intercepteur intercepte toutes les requêtes actualise la période de validité du jeton et interrogera les informations de l'utilisateur enregistrées dans ThreadLocal. Le deuxième intercepteur exécute la fonction d'interception et intercepte le chemin qui nécessite une connexion.
Implémentation de l'intercepteur de jeton d'actualisation?:
public class RefreshTokenInterceptor implements HandlerInterceptor { private StringRedisTemplate stringRedisTemplate; public RefreshTokenInterceptor(StringRedisTemplate stringRedisTemplate){ this.stringRedisTemplate = stringRedisTemplate; } @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 1. 獲取請求頭中的 token String token = request.getHeader("authorization"); if (StrUtil.isBlank(token)) { return true; } // 2. 基于 token 獲取 redis 中的用戶 String tokenKey = "login:token:" + token; Map<Object, Object> userMap = stringRedisTemplate.opsForHash().entries(tokenKey); // 3. 判斷用戶是否存在 if (userMap.isEmpty()) { return true; } // 5. 將查詢到的 Hash 數(shù)據(jù)轉(zhuǎn)為 UserDTO 對象 UserDTO user = BeanUtil.fillBeanWithMap(userMap, new UserDTO(), false); // 6. 存在,保存用戶信息到 ThreadLocal UserHolder.saveUser(user); // 7. 刷新 token 有效期 30 min stringRedisTemplate.expire(tokenKey, 30, TimeUnit.MINUTES); // 8. 放行 return true; } }
Implémentation de l'intercepteur de vérification de connexion?:
public class LoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 1. 獲取 session HttpSession session = request.getSession(); // 2. 獲取 session 中的用戶 UserDTO user = (UserDTO) session.getAttribute("user"); // 3. 判斷用戶是否存在 if(user == null){ // 4. 不存在,攔截,返回 401 未授權(quán) response.setStatus(401); return false; } // 5. 存在,保存用戶信息到 ThreadLocal UserHolder.saveUser(user); // 6. 放行 return true; } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // 移除用戶,避免內(nèi)存泄露 UserHolder.removeUser(); } }
Implémentation de la classe UserHolder?: Cette classe définit un ThreadLocal statique
public class UserHolder { private static final ThreadLocal<UserDTO> tl = new ThreadLocal<>(); public static void saveUser(UserDTO user){ tl.set(user); } public static UserDTO getUser(){ return tl.get(); } public static void removeUser(){ tl.remove(); } }
Intercepteur de configuration?:
@Configuration public class MvcConfig implements WebMvcConfigurer { @Resource private StringRedisTemplate stringRedisTemplate; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new RefreshTokenInterceptor(stringRedisTemplate)) .addPathPatterns("/**").order(0); registry.addInterceptor(new LoginInterceptor()) .excludePathPatterns( "/user/login", "/user/code" ).order(1); } }
Description de la demande frontale?:
Description | |
---|---|
Méthode de requête | POST |
Chemin de la requête | /user/me |
Paramètres de la requête | Aucun |
Valeur de retour | Aucun |
Implémentation de l'interface backend?:
@Slf4j @Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService { @Override public Result me() { UserDTO user = UserHolder.getUser(); return Result.ok(user); } }
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Outils d'IA chauds

Undress AI Tool
Images de déshabillage gratuites

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Clothoff.io
Dissolvant de vêtements AI

Video Face Swap
échangez les visages dans n'importe quelle vidéo sans effort grace à notre outil d'échange de visage AI entièrement gratuit?!

Article chaud

Outils chauds

Bloc-notes++7.3.1
éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Redis est supérieur aux bases de données traditionnelles dans des scénarios élevés de concurrence et de faible latence, mais ne convient pas aux requêtes complexes et au traitement des transactions. 1.redis utilise le stockage de mémoire, la lecture rapide et la vitesse d'écriture, adapté aux exigences élevées de la concurrence et de la latence faible. 2. Les bases de données traditionnelles sont basées sur le disque, prennent en charge les requêtes complexes et le traitement des transactions, et ont une cohérence et une persistance des données solides. 3. Redis convient comme complément ou substitut aux bases de données traditionnelles, mais elle doit être sélectionnée en fonction des besoins commerciaux spécifiques.

Linux System restreint les ressources utilisateur via la commande UliMIT pour éviter une utilisation excessive des ressources. 1.Ulimit est une commande shell intégrée qui peut limiter le nombre de descripteurs de fichiers (-n), la taille de la mémoire (-v), le nombre de threads (-u), etc., qui sont divisés en limite douce (valeur effective actuelle) et limite dure (limite supérieure maximale). 2. Utilisez directement la commande ulimit pour une modification temporaire, telle que Ulimit-N2048, mais elle n'est valable que pour la session en cours. 3. Pour un effet permanent, vous devez modifier /etc/security/limits.conf et les fichiers de configuration PAM, et ajouter SessionRequiredPam_limits.so. 4. Le service SystemD doit définir Lim dans le fichier unitaire

Redis va au-delà des bases de données SQL en raison de ses performances élevées et de sa flexibilité. 1) Redis atteint une vitesse de lecture et d'écriture extrêmement rapide grace à un stockage de mémoire. 2) Il prend en charge une variété de structures de données, telles que les listes et les collections, adaptées au traitement des données complexes. 3) Le modèle unique simplifie le développement, mais une concurrence élevée peut devenir un goulot d'étranglement.

Les étapes pour créer un site Web PHP dynamique à l'aide de PHPStudy incluent: 1. Installez PHPStudy et démarrez le service; 2. Configurer le répertoire racine du site Web et la connexion de la base de données; 3. écrivez des scripts PHP pour générer du contenu dynamique; 4. Débogage et optimiser les performances du site Web. Grace à ces étapes, vous pouvez créer un site Web dynamique PHP entièrement fonctionnel à partir de zéro.

La stratégie de mise en cache de la page de Laravel peut améliorer considérablement les performances du site Web. 1) Utilisez des fonctions de cache d'assistance pour implémenter la mise en cache de page, telles que la méthode Cache :: Rappelez-vous. 2) Sélectionnez le backend de cache approprié, tel que redis. 3) Faites attention aux problèmes de cohérence des données et vous pouvez utiliser des caches à grain fin ou des auditeurs d'événements pour effacer le cache. 4) Une optimisation supplémentaire est combinée avec le cache de routage, les étiquettes de cache et de cache d'afficher. En appliquant rationnellement ces stratégies, les performances du site Web peuvent être effectivement améliorées.

UserredisinsteaDofatraditionalDatabase, quand vous appliquez la prévision de la civil et de la division

Les étapes de dépannage et de réparation des défaillances de réplication des esclaves de Redis incluent: 1. Vérifiez la connexion réseau et utilisez Ping ou Telnet pour tester la connectivité; 2. Vérifiez le fichier de configuration Redis pour vous assurer que la réplique et le temps de remplacement sont définis correctement; 3. Vérifiez le fichier journal Redis et recherchez des informations d'erreur; 4. S'il s'agit d'un problème de réseau, essayez de redémarrer le périphérique réseau ou de changer le chemin alternatif; 5. S'il s'agit d'un problème de configuration, modifiez le fichier de configuration; 6. S'il s'agit d'un problème de synchronisation des données, utilisez la commande SlaveOf pour réintégrer les données.

RedisisuniqueComperedTotraditionalsqldatabasesInSeverAlways: 1) itoperatesprimy inmemory, permettant à la base de laadandwriteoperations.2)
