当前位置: 首页 > news >正文

东莞网站搭建哪家强seo软文代写

东莞网站搭建哪家强,seo软文代写,二级域名网站如何,次世代建模培训文章目录 背景环境代码实现0. 项目结构图(供参考)1. 数据库中的表(供参考)2. 依赖(pom.xml)3. 配置文件(application.yml)4. 配置文件(application-dev.yml)5…

文章目录

    • 背景
    • 环境
    • 代码实现
      • 0. 项目结构图(供参考)
      • 1. 数据库中的表(供参考)
      • 2. 依赖(pom.xml)
      • 3. 配置文件(application.yml)
      • 4. 配置文件(application-dev.yml)
      • 5. UserLoginDTO
      • 6. DemoConstant
      • 7. User(后来才用的lombok,没有统一写法)
      • 8. UserMapper
      • 9. UserService(供参考)
      • 10. UserController
      • 11. RedisConfig
      • 12. 统一返回结果
      • 13. 启动类LoginDemoApplication
    • 测试登录接口(一分钟内五次密码全错,触发账号锁定登录权限)
      • 第一次测试(300ms)
      • 第二次测试(32ms)
      • 第三次测试(22ms)
      • 第四次测试(12ms)
      • 第五次测试(8ms)
    • 总结

背景

前两天被面试到这个问题,最初回答的不是很合理,登录次数这方面记录还一直往数据库上面想,后来感觉在数据库中加一个登录日志表,来查询一段时间内用户登录的次数,现在看来,自己还是太年轻了,做个登录限制肯定是为了防止数据库高并发,加一个表来记录登录日志,这就把请求都打到数据库了,后来看了前辈们的解决方案,可以用Redis来实现,包括登录次数和账号锁定,我最开始在回答这个问题的时候只回答到了账号锁定用Redis做管理,前者登录次数回答的比较差劲,后来我也及时复盘了这次面试,就标题的内容做出基本实现

环境

Java8、MySQL8、Redis、IDEA,环境支持的同学可以参考这份代码实现以下

代码实现

0. 项目结构图(供参考)

在这里插入图片描述

1. 数据库中的表(供参考)

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- Table structure for login_demo_user
-- ----------------------------
DROP TABLE IF EXISTS `login_demo_user`;
CREATE TABLE `login_demo_user`  (`id` bigint NOT NULL COMMENT '主键',`username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户名',`password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '密码',PRIMARY KEY (`id`, `username`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;-- ----------------------------
-- Records of login_demo_user
-- ----------------------------
INSERT INTO `login_demo_user` VALUES (1, 'hh', 'hh');SET FOREIGN_KEY_CHECKS = 1;

2. 依赖(pom.xml)

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.2.1.RELEASE</version><relativePath/></parent><groupId>com.openallzzz</groupId><artifactId>logindemo</artifactId><version>0.0.1-SNAPSHOT</version><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.0</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.1</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.20</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>

3. 配置文件(application.yml)

server:port: 8080spring:profiles:active: devmain:allow-circular-references: truedatasource:druid:driver-class-name: ${datasource.driver-class-name}url: jdbc:mysql://${datasource.host}:${datasource.port}/${datasource.database}?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=trueusername: ${datasource.username}password: ${datasource.password}redis:host: ${redis.host}port: ${redis.port}database: ${redis.database}mybatis:#mapper配置文件mapper-locations: classpath:mapper/*.xmltype-aliases-package: com.openallzzz.logindemo.entityconfiguration:#开启驼峰命名map-underscore-to-camel-case: truelogging:level:com:openallzzz:mapper: debugservice: infocontroller: info

4. 配置文件(application-dev.yml)

datasource:driver-class-name: com.mysql.cj.jdbc.Driverhost: localhostport: 3306database: testdbusername: rootpassword: root
redis:host: localhostport: 6379database: 1

5. UserLoginDTO

package com.openallzzz.logindemo.dto;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserLoginDTO {private String username;private String password;}

6. DemoConstant

package com.openallzzz.logindemo.constant;public class DemoConstant {// 每分钟限制登录的最大次数public static final int MAX_LOGIN_TIMRS_PER_MINUTE = 5;
}

7. User(后来才用的lombok,没有统一写法)

package com.openallzzz.logindemo.entity;public class User {private Long id;private String username;private String password;public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}
}

8. UserMapper

package com.openallzzz.logindemo.mapper;import com.openallzzz.logindemo.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;@Mapper
public interface UserMapper {@Select("select id, username, password from login_demo_user where username = #{username}")User selectByUsername(String username);}

9. UserService(供参考)

package com.openallzzz.logindemo.service;import com.openallzzz.logindemo.constant.DemoConstant;
import com.openallzzz.logindemo.dto.UserLoginDTO;
import com.openallzzz.logindemo.entity.User;
import com.openallzzz.logindemo.mapper.UserMapper;
import com.openallzzz.logindemo.result.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;import java.util.concurrent.TimeUnit;@Service
@Slf4j
public class UserService {@Autowiredprivate UserMapper userMapper;@Autowiredprivate RedisTemplate redisTemplate;public Result<String> login(UserLoginDTO userLoginDTO) {if (userLoginDTO == null || userLoginDTO.getUsername() == null || userLoginDTO.getPassword() == null) {return Result.error("用户信息不完整!");}String username = userLoginDTO.getUsername();String password = userLoginDTO.getPassword();boolean lockStatus = getLockStatus(username);if (lockStatus) {return Result.error("失败次数过多,请稍后重试");}User user = userMapper.selectByUsername(username);if (user.getPassword().equals(password)) {clearLastCount(username);clearLockStatus(username);return Result.success();} else {int lastCount = getLastCount(username);if (lastCount + 1 == DemoConstant.MAX_LOGIN_TIMRS_PER_MINUTE) {setLockStatus(username);return Result.error("失败次数过多,请稍后重试");} else {setLastCount(username);return Result.error("登录失败,请检查用户名或密码,再重试");}}}private void clearLockStatus(String username) {log.info("清除用户锁定状态:{}", username);String key = "Lock" + ":" + username;redisTemplate.delete(key);}private void clearLastCount(String username) {log.info("将用户登录次数还原:{}", username);String key = "Count" + ":" + username;redisTemplate.delete(key);}private int getLastCount(String username) {log.info("获取用户一分钟内已经失败登录了多少次:{}", username);String key = "Count" + ":" + username;Integer count = (Integer) redisTemplate.opsForValue().get(key);return count == null ? 0 : count;}private void setLastCount(String username) {log.info("设置用户一分钟内已经失败登录了多少次:{}", username);String key = "Count" + ":" + username;redisTemplate.opsForValue().set(key, getLastCount(username) + 1, 1, TimeUnit.MINUTES);}private void setLockStatus(String username) {log.info("锁定用户,限制其登录:{}", username);String key = "Lock" + ":" + username;redisTemplate.opsForValue().set(key, "lock", 2, TimeUnit.HOURS);}private boolean getLockStatus(String username) {log.info("获取用户是否被限制其登录:{}", username);String key = "Lock" + ":" + username;String o = (String) redisTemplate.opsForValue().get(key);if ("lock".equals(o)) return true;return false;}}

10. UserController

package com.openallzzz.logindemo.controller;import com.openallzzz.logindemo.dto.UserLoginDTO;
import com.openallzzz.logindemo.result.Result;
import com.openallzzz.logindemo.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {@Autowiredprivate UserService userService;@PostMapping("/login")public Result<String> login(@RequestBody UserLoginDTO userLoginDTO) {log.info("用户登录:{}", userLoginDTO);return userService.login(userLoginDTO);}}

11. RedisConfig

package com.openallzzz.logindemo.config;import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;@Configuration
@EnableCaching
public class RedisConfig {@Bean(name = "redisTemplate")public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory){RedisTemplate<String,Object> template = new RedisTemplate<>();//配置连接工厂template.setConnectionFactory(factory);//使用jackson序列化和反序列value的值,Jackson2JsonRedisSerializer jacksonSerializer = new Jackson2JsonRedisSerializer(Object.class);ObjectMapper mapper = new ObjectMapper();//指定需要序列化的范围,All表示field、get和set,以及修饰符范围,ANY表示所有范围,包括privatemapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);jacksonSerializer.setObjectMapper(mapper);//设置template中value使用Jackson2JsonRedisSerializer序列化template.setValueSerializer(jacksonSerializer);//设置template中key使用StringRedisSerializer序列化template.setKeySerializer(new StringRedisSerializer());//这是hash中key和value的序列化方式,key采用StringRedisSerializer,value采用Jackson2JsonRedisSerializertemplate.setHashKeySerializer(new StringRedisSerializer());template.setHashValueSerializer(jacksonSerializer);//使template属性生效template.afterPropertiesSet();return template;}
}

12. 统一返回结果

package com.openallzzz.logindemo.result;import lombok.Data;import java.io.Serializable;/*** 后端统一返回结果* @param <T>*/
@Data
public class Result<T> implements Serializable {private Integer code; //编码:1成功,0和其它数字为失败private String msg; //错误信息private T data; //数据public static <T> Result<T> success() {Result<T> result = new Result<T>();result.code = 1;return result;}public static <T> Result<T> success(T object) {Result<T> result = new Result<T>();result.data = object;result.code = 1;return result;}public static <T> Result<T> error(String msg) {Result result = new Result();result.msg = msg;result.code = 0;return result;}}

13. 启动类LoginDemoApplication

package com.openallzzz.logindemo;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class LoginDemoApplication {public static void main(String[] args) {SpringApplication.run(LoginDemoApplication.class, args);}}

测试登录接口(一分钟内五次密码全错,触发账号锁定登录权限)

第一次测试(300ms)

在这里插入图片描述

第二次测试(32ms)

在这里插入图片描述

第三次测试(22ms)

在这里插入图片描述

第四次测试(12ms)

在这里插入图片描述

第五次测试(8ms)

在这里插入图片描述

总结

登录业务预先判断了该账号是否被锁定,如果短期内有大量登录请求(用户不断试错、被恶意攻击),压力只会给到Redis,从而避免DB被大量请求打中。

http://www.dinnco.com/news/23881.html

相关文章:

  • 码云可以做博客网站吗端点seo博客
  • 大型行业门户网站开发建设买转发链接
  • 网站建设的一般过程广告设计与制作需要学什么
  • html做的网站排版错误优秀品牌策划方案
  • 正规的家居行业网站开发百度推广电话是多少
  • xml做web网站公司网络推广
  • 怎么把网站开发成crx优化网站推广排名
  • 西安网站开发招聘明天上海封控16个区
  • 数码科技网站获客软件
  • 个人做网站要备案吗天津搜索引擎seo
  • 舟山网站建设环球网疫情最新
  • 婚庆网站开发的意义东莞网站建设方案外包
  • 政府门户网站 建设关联词有哪些
  • 完整网站源码下载网站seo报告
  • wordpress dux3.0主题科学新概念seo外链平台
  • 叫人做网站多少钱百度宣传推广费用
  • 做淘宝详情的网站提交网址给百度
  • jsp动态网站开发技术毕业论文网站推广策划书模板
  • 做网站实训报告广州seo推荐
  • 平阳手机网站制作网络营销与策划实践报告
  • 网站功能说明书大连网站制作
  • 乐清做网站的公司网站权重
  • 网页设计个人简历怎么做厦门seo关键词排名
  • 哪个网站做化妆品效果好学技术的培训学校
  • wordpress flask上海网站seoseodian
  • 企点qq是什么seo网站排名优化教程
  • 做网站3年3万营销型网站设计
  • 企业集团网站建设与运营管理培训
  • 网站模版超市自助建站申请
  • 做驾校题目用什么网站好百度搜索引擎的使用方法