0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

三次輸入密碼錯誤怎么辦?

jf_ro2CN3Fa ? 來源:稀土掘金 ? 2023-11-28 10:00 ? 次閱讀

1 故事背景

忘記密碼這件事,相信絕大多數(shù)人都遇到過,輸一次錯一次,錯到幾次以上,就不允許你繼續(xù)嘗試了。

但當(dāng)你嘗試重置密碼,又發(fā)現(xiàn)新密碼不能和原密碼重復(fù):

雖然,但是,密碼還是很重要的,順便我有了一個問題:三次輸錯密碼后,系統(tǒng)是怎么做到不讓我繼續(xù)嘗試的?

2 我想了想,有如下幾個問題需要搞定

是只有輸錯密碼才鎖定,還是賬戶名和密碼任何一個輸錯就鎖定?

輸錯之后也不是完全凍結(jié),為啥隔了幾分鐘又可以重新輸了?

技術(shù)棧到底麻不麻煩?

去網(wǎng)上搜了搜,也問了下ChatGPT,找到一套解決方案:SpringBoot+Redis+Lua腳本。

這套方案也不算新,很早就有人在用了,不過難得是自己想到的問題和解法,就記錄一下吧。

順便回答一下上面的三個問題:

鎖定的是IP,不是輸入的賬戶名或者密碼,也就是說任一一個輸錯3次就會被鎖定

Redis的Lua腳本中實現(xiàn)了key過期策略,當(dāng)key消失時鎖定自然也就消失了

技術(shù)棧同SpringBoot+Redis+Lua腳本

3 那么自己動手實現(xiàn)一下

前端部分

首先寫一個賬密輸入頁面,使用很簡單HTML加表單提交




登錄頁面




用戶名

密碼





效果如下:

e9fe2882-8b73-11ee-939d-92fbcf53809c.png

后端部分

技術(shù)選型分析

首先我們畫一個流程圖來分析一下這個登錄限制流程

ea140d8c-8b73-11ee-939d-92fbcf53809c.png

從流程圖上看,首先訪問次數(shù)的統(tǒng)計與判斷不是在登錄邏輯執(zhí)行后,而是執(zhí)行前就加1了;

其次登錄邏輯的成功與失敗并不會影響到次數(shù)的統(tǒng)計;

最后還有一點流程圖上沒有體現(xiàn)出來,這個次數(shù)的統(tǒng)計是有過期時間的,當(dāng)過期之后又可以重新登錄了。

那為什么是Redis+Lua腳本呢?

Redis的選擇不難看出,這個流程比較重要的是存在一個用來計數(shù)的變量,這個變量既要滿足分布式讀寫需求,還要滿足全局遞增或遞減的需求,那Redis的incr方法是最優(yōu)選了。

那為什么需要Lua腳本呢?流程上在驗證用戶操作前有些操作,如圖:

ea32f9c2-8b73-11ee-939d-92fbcf53809c.png

這里至少有3步Redis的操作,get、incr、expire,如果全放到應(yīng)用里面來操作,有點慢且浪費資源。

Lua腳本的優(yōu)點如下:

減少網(wǎng)絡(luò)開銷。 可以將多個請求通過腳本的形式一次發(fā)送,減少網(wǎng)絡(luò)時延。

原子操作。 Redis會將整個腳本作為一個整體執(zhí)行,中間不會被其他請求插入。因此在腳本運行過程中無需擔(dān)心會出現(xiàn)競態(tài)條件,無需使用事務(wù)。

復(fù)用。 客戶端發(fā)送的腳本會永久存在redis中,這樣其他客戶端可以復(fù)用這一腳本,而不需要使用代碼完成相同的邏輯。

最后為了增加功能的復(fù)用性,我打算使用Java注解的方式實現(xiàn)這個功能。

代碼實現(xiàn)

項目結(jié)構(gòu)如下

ea4302ae-8b73-11ee-939d-92fbcf53809c.png

配置文件

pom.xml



4.0.0

org.springframework.boot
spring-boot-starter-parent
2.7.11
 

com.example
LoginLimit
0.0.1-SNAPSHOT
LoginLimit
DemoprojectforSpringBoot

1.8



org.springframework.boot
spring-boot-starter-web



org.springframework.boot
spring-boot-starter-test
test

 

org.springframework.boot
spring-boot-starter-data-redis

 

redis.clients
jedis

 

org.aspectj
aspectjweaver

 

org.apache.commons
commons-lang3

 

com.google.guava
guava
23.0

 

org.projectlombok
lombok
true






org.springframework.boot
spring-boot-maven-plugin





application.properties

#Redis配置
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=
spring.redis.timeout=1000
#Jedis配置
spring.redis.jedis.pool.min-idle=0
spring.redis.jedis.pool.max-idle=500
spring.redis.jedis.pool.max-active=2000
spring.redis.jedis.pool.max-wait=10000

注解部分

LimitCount.java

packagecom.example.loginlimit.annotation;

importjava.lang.annotation.ElementType;
importjava.lang.annotation.Retention;
importjava.lang.annotation.RetentionPolicy;
importjava.lang.annotation.Target;

/**
*次數(shù)限制注解
*作用在接口方法上
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public@interfaceLimitCount{
/**
*資源名稱,用于描述接口功能
*/
Stringname()default"";

/**
*資源key
*/
Stringkey()default"";

/**
*keyprefix
*
*@return
*/
Stringprefix()default"";

/**
*時間的,單位秒
*默認(rèn)60s過期
*/
intperiod()default60;

/**
*限制訪問次數(shù)
*默認(rèn)3次
*/
intcount()default3;
}

核心處理邏輯類:LimitCountAspect.java

packagecom.example.loginlimit.aspect;

importjava.io.Serializable;
importjava.lang.reflect.Method;
importjava.util.Objects;

importjavax.servlet.http.HttpServletRequest;

importcom.example.loginlimit.annotation.LimitCount;
importcom.example.loginlimit.util.IPUtil;
importcom.google.common.collect.ImmutableList;
importlombok.extern.slf4j.Slf4j;
importorg.apache.commons.lang3.StringUtils;
importorg.aspectj.lang.ProceedingJoinPoint;
importorg.aspectj.lang.annotation.Around;
importorg.aspectj.lang.annotation.Aspect;
importorg.aspectj.lang.annotation.Pointcut;
importorg.aspectj.lang.reflect.MethodSignature;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.data.redis.core.RedisTemplate;
importorg.springframework.data.redis.core.script.DefaultRedisScript;
importorg.springframework.data.redis.core.script.RedisScript;
importorg.springframework.stereotype.Component;
importorg.springframework.web.context.request.RequestContextHolder;
importorg.springframework.web.context.request.ServletRequestAttributes;

@Slf4j
@Aspect
@Component
publicclassLimitCountAspect{

privatefinalRedisTemplatelimitRedisTemplate;

@Autowired
publicLimitCountAspect(RedisTemplatelimitRedisTemplate){
this.limitRedisTemplate=limitRedisTemplate;
}

@Pointcut("@annotation(com.example.loginlimit.annotation.LimitCount)")
publicvoidpointcut(){
//donothing
}

@Around("pointcut()")
publicObjectaround(ProceedingJoinPointpoint)throwsThrowable{
HttpServletRequestrequest=((ServletRequestAttributes)Objects.requireNonNull(
RequestContextHolder.getRequestAttributes())).getRequest();

MethodSignaturesignature=(MethodSignature)point.getSignature();
Methodmethod=signature.getMethod();
LimitCountannotation=method.getAnnotation(LimitCount.class);
//注解名稱
Stringname=annotation.name();
//注解key
Stringkey=annotation.key();
//訪問IP
Stringip=IPUtil.getIpAddr(request);
//過期時間
intlimitPeriod=annotation.period();
//過期次數(shù)
intlimitCount=annotation.count();

ImmutableListkeys=ImmutableList.of(StringUtils.join(annotation.prefix()+"_",key,ip));
StringluaScript=buildLuaScript();
RedisScriptredisScript=newDefaultRedisScript<>(luaScript,Number.class);
Numbercount=limitRedisTemplate.execute(redisScript,keys,limitCount,limitPeriod);
log.info("IP:{}第{}次訪問key為{},描述為[{}]的接口",ip,count,keys,name);
if(count!=null&&count.intValue()<=?limitCount)?{
????????????return?point.proceed();
????????}?else?{
????????????return?"接口訪問超出頻率限制";
????????}
????}

????/**
?????*?限流腳本
?????*?調(diào)用的時候不超過閾值,則直接返回并執(zhí)行計算器自加。
?????*
?????*?@return?lua腳本
?????*/
????private?String?buildLuaScript()?{
????????return?"local?c"?+
????????????"
c?=?redis.call('get',KEYS[1])"?+
????????????"
if?c?and?tonumber(c)?>tonumber(ARGV[1])then"+
"
returnc;"+
"
end"+
"
c=redis.call('incr',KEYS[1])"+
"
iftonumber(c)==1then"+
"
redis.call('expire',KEYS[1],ARGV[2])"+
"
end"+
"
returnc;";
}

}

獲取IP地址的功能我寫了一個工具類IPUtil.java,代碼如下:

packagecom.example.loginlimit.util;

importjavax.servlet.http.HttpServletRequest;

publicclassIPUtil{

privatestaticfinalStringUNKNOWN="unknown";

protectedIPUtil(){

}

/**
*獲取IP地址
*使用Nginx等反向代理軟件,則不能通過request.getRemoteAddr()獲取IP地址
*如果使用了多級反向代理的話,X-Forwarded-For的值并不止一個,而是一串IP地址,
*X-Forwarded-For中第一個非unknown的有效IP字符串,則為真實IP地址
*/
publicstaticStringgetIpAddr(HttpServletRequestrequest){
Stringip=request.getHeader("x-forwarded-for");
if(ip==null||ip.length()==0||UNKNOWN.equalsIgnoreCase(ip)){
ip=request.getHeader("Proxy-Client-IP");
}
if(ip==null||ip.length()==0||UNKNOWN.equalsIgnoreCase(ip)){
ip=request.getHeader("WL-Proxy-Client-IP");
}
if(ip==null||ip.length()==0||UNKNOWN.equalsIgnoreCase(ip)){
ip=request.getRemoteAddr();
}
return"0000:1".equals(ip)?"127.0.0.1":ip;
}

}

另外就是Lua限流腳本的說明,腳本代碼如下:

privateStringbuildLuaScript(){
return"localc"+
"
c=redis.call('get',KEYS[1])"+
"
ifcandtonumber(c)>tonumber(ARGV[1])then"+
"
returnc;"+
"
end"+
"
c=redis.call('incr',KEYS[1])"+
"
iftonumber(c)==1then"+
"
redis.call('expire',KEYS[1],ARGV[2])"+
"
end"+
"
returnc;";
}

這段腳本有一個判斷, tonumber(c) > tonumber(ARGV[1])這行表示如果當(dāng)前key 的值大于了limitCount,直接返回;否則調(diào)用incr方法進(jìn)行累加1,且調(diào)用expire方法設(shè)置過期時間。

最后就是RedisConfig.java,代碼如下:

packagecom.example.loginlimit.config;

importjava.io.IOException;
importjava.io.Serializable;
importjava.time.Duration;
importjava.util.Arrays;

importcom.fasterxml.jackson.core.JsonProcessingException;
importcom.fasterxml.jackson.databind.ObjectMapper;
importorg.apache.commons.lang3.StringUtils;
importorg.springframework.beans.factory.annotation.Value;
importorg.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
importorg.springframework.cache.CacheManager;
importorg.springframework.cache.annotation.CachingConfigurerSupport;
importorg.springframework.cache.interceptor.KeyGenerator;
importorg.springframework.context.annotation.Bean;
importorg.springframework.context.annotation.Configuration;
importorg.springframework.data.redis.cache.RedisCacheManager;
importorg.springframework.data.redis.connection.RedisConnectionFactory;
importorg.springframework.data.redis.connection.RedisPassword;
importorg.springframework.data.redis.connection.RedisStandaloneConfiguration;
importorg.springframework.data.redis.connection.jedis.JedisClientConfiguration;
importorg.springframework.data.redis.connection.jedis.JedisConnectionFactory;
importorg.springframework.data.redis.core.RedisTemplate;
importorg.springframework.data.redis.core.StringRedisTemplate;
importorg.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
importorg.springframework.data.redis.serializer.RedisSerializer;
importorg.springframework.data.redis.serializer.SerializationException;
importorg.springframework.data.redis.serializer.StringRedisSerializer;
importredis.clients.jedis.JedisPool;
importredis.clients.jedis.JedisPoolConfig;

@Configuration
publicclassRedisConfigextendsCachingConfigurerSupport{

@Value("${spring.redis.host}")
privateStringhost;

@Value("${spring.redis.port}")
privateintport;

@Value("${spring.redis.password}")
privateStringpassword;

@Value("${spring.redis.timeout}")
privateinttimeout;

@Value("${spring.redis.jedis.pool.max-idle}")
privateintmaxIdle;

@Value("${spring.redis.jedis.pool.max-wait}")
privatelongmaxWaitMillis;

@Value("${spring.redis.database:0}")
privateintdatabase;

@Bean
publicJedisPoolredisPoolFactory(){
JedisPoolConfigjedisPoolConfig=newJedisPoolConfig();
jedisPoolConfig.setMaxIdle(maxIdle);
jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
if(StringUtils.isNotBlank(password)){
returnnewJedisPool(jedisPoolConfig,host,port,timeout,password,database);
}else{
returnnewJedisPool(jedisPoolConfig,host,port,timeout,null,database);
}
}

@Bean
JedisConnectionFactoryjedisConnectionFactory(){
RedisStandaloneConfigurationredisStandaloneConfiguration=newRedisStandaloneConfiguration();
redisStandaloneConfiguration.setHostName(host);
redisStandaloneConfiguration.setPort(port);
redisStandaloneConfiguration.setPassword(RedisPassword.of(password));
redisStandaloneConfiguration.setDatabase(database);

JedisClientConfiguration.JedisClientConfigurationBuilderjedisClientConfiguration=JedisClientConfiguration
.builder();
jedisClientConfiguration.connectTimeout(Duration.ofMillis(timeout));
jedisClientConfiguration.usePooling();
returnnewJedisConnectionFactory(redisStandaloneConfiguration,jedisClientConfiguration.build());
}

@Bean(name="redisTemplate")
@SuppressWarnings({"rawtypes"})
@ConditionalOnMissingBean(name="redisTemplate")
publicRedisTemplateredisTemplate(RedisConnectionFactoryredisConnectionFactory){
RedisTemplatetemplate=newRedisTemplate<>();
//使用fastjson序列化
JacksonRedisSerializerjacksonRedisSerializer=newJacksonRedisSerializer<>(Object.class);
//value值的序列化采用fastJsonRedisSerializer
template.setValueSerializer(jacksonRedisSerializer);
template.setHashValueSerializer(jacksonRedisSerializer);
//key的序列化采用StringRedisSerializer
template.setKeySerializer(newStringRedisSerializer());
template.setHashKeySerializer(newStringRedisSerializer());

template.setConnectionFactory(redisConnectionFactory);
returntemplate;
}

//緩存管理器
@Bean
publicCacheManagercacheManager(RedisConnectionFactoryredisConnectionFactory){
RedisCacheManager.RedisCacheManagerBuilderbuilder=RedisCacheManager.RedisCacheManagerBuilder
.fromConnectionFactory(redisConnectionFactory);
returnbuilder.build();
}

@Bean
@ConditionalOnMissingBean(StringRedisTemplate.class)
publicStringRedisTemplatestringRedisTemplate(RedisConnectionFactoryredisConnectionFactory){
StringRedisTemplatetemplate=newStringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
returntemplate;
}

@Bean
publicKeyGeneratorwiselyKeyGenerator(){
return(target,method,params)->{
StringBuildersb=newStringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
Arrays.stream(params).map(Object::append);
returnsb.toString();
};
}

@Bean
publicRedisTemplatelimitRedisTemplate(RedisConnectionFactoryredisConnectionFactory){
RedisTemplatetemplate=newRedisTemplate<>();
template.setKeySerializer(newStringRedisSerializer());
template.setValueSerializer(newGenericJackson2JsonRedisSerializer());
template.setConnectionFactory(redisConnectionFactory);
returntemplate;
}
}

classJacksonRedisSerializerimplementsRedisSerializer{
privateClassclazz;
privateObjectMappermapper;

JacksonRedisSerializer(Classclazz){
super();
this.clazz=clazz;
this.mapper=newObjectMapper();
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
}

@Override
publicbyte[]serialize(Tt)throwsSerializationException{
try{
returnmapper.writeValueAsBytes(t);
}catch(JsonProcessingExceptione){
e.printStackTrace();
returnnull;
}
}

@Override
publicTdeserialize(byte[]bytes)throwsSerializationException{
if(bytes.length<=?0)?{
????????????return?null;
????????}
????????try?{
????????????return?mapper.readValue(bytes,?clazz);
????????}?catch?(IOException?e)?{
????????????e.printStackTrace();
????????????return?null;
????????}
????}
}

LoginController.java

packagecom.example.loginlimit.controller;

importjavax.servlet.http.HttpServletRequest;

importcom.example.loginlimit.annotation.LimitCount;
importlombok.extern.slf4j.Slf4j;
importorg.apache.commons.lang3.StringUtils;
importorg.springframework.web.bind.annotation.GetMapping;
importorg.springframework.web.bind.annotation.RequestParam;
importorg.springframework.web.bind.annotation.RestController;

@Slf4j
@RestController
publicclassLoginController{

@GetMapping("/login")
@LimitCount(key="login",name="登錄接口",prefix="limit")
publicStringlogin(
@RequestParam(required=true)Stringusername,
@RequestParam(required=true)Stringpassword,HttpServletRequestrequest)throwsException{
if(StringUtils.equals("張三",username)&&StringUtils.equals("123456",password)){
return"登錄成功";
}
return"賬戶名或密碼錯誤";
}

}

LoginLimitApplication.java

packagecom.example.loginlimit;

importorg.springframework.boot.SpringApplication;
importorg.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
publicclassLoginLimitApplication{

publicstaticvoidmain(String[]args){
SpringApplication.run(LoginLimitApplication.class,args);
}

}

4 演示一下效果

ea62eb28-8b73-11ee-939d-92fbcf53809c.png

上面這套限流的邏輯感覺用在小型或中型的項目上應(yīng)該問題不大,不過目前的登錄很少有直接鎖定賬號不能輸入的,一般都是彈出一個驗證碼框,讓你輸入驗證碼再提交。我覺得用我這套邏輯改改應(yīng)該不成問題,核心還是接口嘗試次數(shù)的限制嘛!

審核編輯:黃飛

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • ip地址
    +關(guān)注

    關(guān)注

    0

    文章

    303

    瀏覽量

    17055
  • Redis
    +關(guān)注

    關(guān)注

    0

    文章

    375

    瀏覽量

    10875
  • ChatGPT
    +關(guān)注

    關(guān)注

    29

    文章

    1561

    瀏覽量

    7670
  • SpringBoot
    +關(guān)注

    關(guān)注

    0

    文章

    173

    瀏覽量

    179

原文標(biāo)題:三次輸錯密碼后,系統(tǒng)是怎么做到不讓我繼續(xù)嘗試的?

文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    自動布線換了N 還是那么多錯誤 怎么辦

    `RT 自動布線原件位置換了N 還是那么多錯誤怎么辦啊`
    發(fā)表于 01-02 20:46

    我這個設(shè)計怎么添加讓密碼輸入三次錯誤失效的程序

    怎么把各模塊獨立出來,變?yōu)樽映绦颉?b class='flag-5'>密碼怎么寫三次輸入錯誤失效的程序?
    發(fā)表于 06-18 12:07

    三次握手,四揮手你懂嗎

    程序員面試被問到“三次握手,四揮手”怎么辦?
    發(fā)表于 04-08 07:23

    手機(jī)密碼鎖忘了怎么辦?教你解手機(jī)密碼

    手機(jī)密碼鎖忘了怎么辦? 解話機(jī)鎖:*2767*2878#/*2767*7377#   星碼片復(fù)位:*2767*3855# 也可用于解機(jī)鎖或卡鎖   星顯溫度、電池容量:*#022
    發(fā)表于 02-25 09:49 ?74.5w次閱讀

    電腦密碼忘記了怎么辦_win7系統(tǒng)電腦忘記密碼的處理方法

    現(xiàn)在使用電腦的人越來越多,而各種各樣的密碼也越來越多,很多人在剛剛設(shè)置了電腦密碼后一下就忘記了。電腦密碼忘記了怎么辦?并且現(xiàn)在使用WIN7系統(tǒng)的人也越來越多,WIN7電腦密
    發(fā)表于 10-23 17:00 ?77.6w次閱讀

    TCP三次握手的過程描述

    本文檔主要描述TCP三次握手的過程,一個完整的三次握手也就是 請求---應(yīng)答---再次確認(rèn)
    發(fā)表于 03-02 15:37 ?8次下載

    蘋果iphone7plus的下載密碼忘了怎么辦

    忘記手機(jī)解鎖密碼是用戶經(jīng)常忘記的事情,有很多人都不得不去刷機(jī)解鎖重新設(shè)置。前幾天有個人問小編說iPhone7Plus的解鎖密碼忘記了怎么辦?今天小編就來說說蘋果iPhone解鎖密碼那些
    發(fā)表于 10-13 16:40 ?8440次閱讀

    若忘記了Linux系統(tǒng)的root密碼,該怎么辦?

    很多朋友經(jīng)常會忘記Linux系統(tǒng)的root密碼,linux系統(tǒng)忘記root密碼的情況該怎么辦呢?
    的頭像 發(fā)表于 10-15 16:49 ?1.3w次閱讀

    蘋果iPad忘記了Apple ID密碼怎么辦

    Apple ID密碼忘了怎么辦?蘋果用戶最常見的一個問題是忘記了Apple ID密碼,這樣就沒辦法從App Store下載應(yīng)用了,那么如何才能將密碼找回來呢?一般在蘋果
    的頭像 發(fā)表于 09-11 12:10 ?9w次閱讀
    蘋果iPad忘記了Apple ID<b class='flag-5'>密碼</b>該<b class='flag-5'>怎么辦</b>?

    三次諧波是什么,三次諧波會造成哪些影響

    每次平臺文章過后看見很多朋友問到底什么是三次諧波跟電工有什么關(guān)系?會產(chǎn)生怎樣的影響?如何治理或防止三次諧波的滋生?別急今天就出一期有關(guān)三次諧波的全面講解! ①三次諧波是什么? 答:
    發(fā)表于 11-16 15:44 ?3.1w次閱讀
    <b class='flag-5'>三次</b>諧波是什么,<b class='flag-5'>三次</b>諧波會造成哪些影響

    deepin密碼忘了怎么辦_deepin分區(qū)方案

    為了安全考慮,在安裝 Deepin 系統(tǒng)的時候一定會要用戶設(shè)置好密碼,你只有知道電腦的登錄密碼后,才能夠登錄進(jìn)行一系列的操作,可是萬一忘記了登錄密碼怎么辦呢?這里就教大家一招重設(shè) D
    發(fā)表于 11-11 14:31 ?1.1w次閱讀

    windows不能更改密碼怎么辦

     很多電腦用戶為了加強(qiáng)電腦安全或保護(hù)個人隱私會給電腦設(shè)置開機(jī)密碼,只有正確輸入密碼后才能進(jìn)入桌面操作。但是有些用戶在設(shè)置密碼時卻遇到了一些問題,例如系統(tǒng)彈出Windows不能更改
    的頭像 發(fā)表于 12-23 15:24 ?1.1w次閱讀

    MySQL密碼忘記了怎么辦?MySQL密碼快速重置方法步驟命令示例!

    MySQL密碼忘記了怎么辦?MySQL密碼快速重置方法步驟命令示例! MySQL是一種常用的關(guān)系型數(shù)據(jù)庫管理系統(tǒng),如果你忘記了MySQL的密碼,不必?fù)?dān)心,可以通過一些簡單的步驟來快速重
    的頭像 發(fā)表于 01-12 16:06 ?751次閱讀

    說說TCP三次握手的過程?為什么是三次而不是兩、四?

    說說TCP三次握手的過程?為什么是三次而不是兩、四? TCP三次握手是建立TCP連接的過程,確保數(shù)據(jù)的可靠傳輸。它是由發(fā)送端和接收端完成
    的頭像 發(fā)表于 02-04 11:03 ?681次閱讀

    諧波和三次諧波區(qū)別 二諧波危害沒有三次諧波大?

    諧波和三次諧波區(qū)別 二諧波危害沒有三次諧波大? 在現(xiàn)代電力系統(tǒng)中,諧波問題逐漸引起人們的關(guān)注。諧波是指頻率是基波頻率的倍數(shù)的電流或電壓成分。二
    的頭像 發(fā)表于 04-08 17:11 ?5941次閱讀