Spring Security-ի PasswordEncoder
ինտերֆեյսը օգտագործվում է գախտնաբառի միակողմանի փոխակերպման համար՝ ապահովելու համար, որ այն անվտանգ պահվի: Քանի որ PasswordEncoder
-ը նախատեսված է միակողմանի փոխակերպման համար, այն նախատեսված չէ դեպքերում, երբ գախտնաբառի փոխակերպումը պետք է լինի երկկողմանի (այսինքն՝ տվյալների բազայի մեջ աուտենտիֆիկացիայի համար օգտագործվող հաշվառման տվյալների պահպանման համար): Սովորաբար PasswordEncoder
-ը օգտագործվում է այն գախտնաբառը պահպանելու համար, որն անհրաժեշտ է համեմատել օգտագործողի կողմից աուտենտիֆիկացիայի ժամանակ մատնանշվող գախտնաբառի հետ:
Պահպանված գախտնաբառների պատմությունը
Տարիներ շարունակ գախտնաբառների պահպանման ստանդարտ մեխանիզմը զարգացել է: Սկզբում գախտնաբառները պահվում էին որպես սովորական տեքստեր: Ենթադրվում էր, որ գախտնաբառները անվտանգ են, քանի որ տվյալների պահեստին հասանելիությունը պահանջում էր հաշվառման տվյալներ: Սակայն չարագործները գտան ուղիներ ստանալու մեծ "տվյալների դուրսբերումներ" օգտագործող անունների և գախտնաբառների, օգտագործելով SQL կոդով ներմուծման (SQL Injection) հարձակումներ: Քանի որ ավելի ու ավելի շատ օգտատերերի հաշիվների տվյալներ արտահոսեցին հանրային հասանելիության մեջ, անվտանգության փորձագետներին պարզ դարձավ, որ անհրաժեշտ է ուժեղացնել գախտնաբառների պաշտպանությունը:
Ծրագրավորողներին առաջարկվեց պահել գախտնաբառները միակողմանի հեշինգի ալգորիթմով փոխանցելուց հետո, օրինակ՝ SHA-256: Երբ օգտատերը փորձում է աուտենտիֆիկացվել, հեշված գախտնաբառը համեմատվում է այն գախտնաբառի հետ, որը ուղարկել է այդ օգտատերը: Սա նշանակում էր, որ համակարգին անհրաժեշտ էր պահել միայն գախտնաբառի միակողմանի հեշը: Եթե համակարգը կոտրվի, կբացահայտվեն միայն գախտնաբառների միակողմանի հեշները: Քանի որ հեշերը միակողմանի էին, իսկ գախտնաբառը հեշից ենթադրել հաշվարկային առումով բարդ էր, համակարգում յուրաքանչյուր գախտնաբառ ընտրելու համար ծախսել փորձագետների ջանքեր արժանի չէր: Չարագործները որոշեցին ստեղծել որոնման աղյուսակներ, որոնք հայտնի են որպես ծիածանային աղյուսակներ: Փոխանակ յուրաքանչյուր գախտնաբառը յուրաքանչյուր անգամ գուշակելու, նրանք այն մեկ անգամ հաշվարկում էին և պահում որոնման աղյուսակում:
Ծիածանային աղյուսակների արդյունավետությունը նվազեցնելու համար ծրագրավորողներին առաջարկվեց օգտագործել "աղի" գախտնաբառներ: Փոխանակ միայն գախտնաբառը օգտագործելու որպես հեշավորման ֆունկցիայի մուտքային տվյալներ, յուրաքանչյուր օգտատիրոջ գախտնաբառին մուտքային տվյալներ ներմուծվեցին պատահական բայտեր (այսպես կոչված աղ): Աղն ու օգտատիրոջ գախտնաբառը գերարագացնվեցին հեշավորման ֆունկցիայի միջոցով, ինչի արդյունքում ստացվեց յուրահատուկ հեշ: Աղը պահվում էր օգտատիրոջ գախտնաբառի հետ միասին որպես մատչելիություն տեքստ: Եթե օգտատերը փորձում է աուտենտիֆիկացվել, հեշված գախտնաբառը համեմատվում էր օգտատիրոջ կողմից մուտքագրված աղի ու գախտնաբառի հետ: Ինչևէ, յուրահատուկ աղը նշանակում է, որ ծիածանային աղյուսակները կորցնում են իրենց արդյունավետությունը, քանի որ հեշը տարբեր էր աղի և գախտնաբառի յուրաքանչյուր համակցության համար:
Այս օրերին հասկացվում է, որ կրիպտոգրաֆիական հեշերը (օրինակ՝ SHA-256 ալգորիթմը) այլևս անվտանգ չեն: Պատճառն այն է, որ ժամանակակից սարքավորումներով հնարավոր է մեկ վայրկյանում կատարելու միլիարդավոր հեշի հաշվարկներ: Սա նշանակում է, որ կարելի է հեշտությամբ կոտրել յուրաքանչյուր գախտնաբառ առանձին:
Ծրագրավորողներին այժմ առաջարկվում է օգտագործել ադապտիվ հաշվարկային անհասանելի ֆունկցիաները գախտնաբառը պահելու համար: Գախտնաբառերի վալիդացիան ադապտիվ հաշվարկային անհասանելի ֆունկցիաներով կանխորոշված մոնետային և ծախսերի բարձր մոտարկման կարիք է ունենում (օրինակ՝ պրոցեսորի, հիշողության ռեսուրսների և այլն): Ադապտիվ հաշվարկային անհասանելի ֆունկցիան թույլ է տալիս կազմաձեւել "աշխատանքի տարողությունը և ծախսերը", որը կարող է աճել սարքավորման բարելավման հետ միասին: Ապահովվում է, որ գախտնաբառի վալիդացիան ձեր համակարգով տևի մոտ 1 վայրկյան: Այսպիսի փոխզիջումը նշանակում է, որ չարագործներին ավելի բարդ է կոտրել գախտնաբառը, բայց միեւնույն ժամանակ ձեր համակարգի վրա ծախսված ռեսուրսների չափից ավելի ծանրաբեռնվածություն չստեղծելու համար: Spring Security-ում փորձ է արվում ապահովել բավարար բազային կետ "աշխատանքի տարողության և ծախսերի համար", բայց օգտվողներին առաջարկվում է կազմաձեւել "աշխատանքի տարողության և ծախսերի համար" իրենց համակարգերի համար, քանի որ արտադրողականությունը մեծապես փոխվում է համակարգից համակարգ: Ադապտիվ հաշվարկային անհասանելի ֆունկցիաների օրինակներ, որոնք պետք է օգտագործվեն, են bcrypt, PBKDF2, scrypt և argon2:
Քանի որ ադապտիվ հաշվարկային անհասանելի ֆունկցիաները ենթադրում են մեծ հաշվարկային ռեսուրսների առկայություն, յուրաքանչյուր պահանջի համար օգտատիրոջ անվան և գախտնաբառի վալիդացիան զգալիորեն նվազեցնում է հավելվածի արտադրողականությունը: Spring Security-ն (կամ որևէ այլ գրադարան) չի կարող ազդել գախտնաբառի վալիդացիան արագացնելու վրա, քանի որ պատշաճ անվտանգության մակարդակը հենց այդպես է հասվում, որ վալիդացիան ծանր ռեսուրս պահանջող խնդիր է: Օգտվողներին առաջարկվում է երկարաժամկետ հաշվառման տվյալները (չափավոր անունը և գախտնաբառը) փոխանակել կարճաժամկետ տվյալներով (օրինակ՝ սեսիայի, OAuth տոկենի և այլն): Կարճաժամկետ տվյալները կարելի է արագ վալիդացնել առանց անվտանգության վտանգի:
DelegatingPasswordEncoder
Մինչ Spring Security 5.0-ի տարբերակը, ըստ լռելյայն օգտագործվում էր NoOpPasswordEncoder
-ը, որը պահանջում էր գախտնաբառներ սովորական տեքստի տեսքով: Բաժնի "Գախտնաբառների պատմություն"-ից կարող ենք սպասել, որ ըստ լռելյայն կօգտագործվի ինչ-որ առարկա BCryptPasswordEncoder
-ի նման: Սակայն, այս դեպքում արհամարհվում են երեք իրական խնդիրներ:
-
Շատ համակարգեր են օգտագործում հին գախտնաբառների կոդավորումներ, որոնք դժվար է տեղափոխել
-
Գախտնաբառների պահպանման առավել օպտիմալ մեթոդը նորից կփոխվի
-
Անձնական ուժիացված փոփոխություններ անել հեշերի ֆունկցիաներում աստիճանաբար չէ, երբ հաճախ չի Արտադրվում
Փոխարենը, Spring Security-ն ներկայացնում է DelegatingPasswordEncoder
, որը լուծում է բոլոր այս խնդիրները:
-
Ապահովելով գախտնաբառների կոդավորումը գախտնաբառերի պահպանման ընթացիկ հանձնարարականների օգտագործմամբ
-
Հնարավորություն տալով վալիդացնել գախտնաբառները ժամանակակից և դարեղեն ձևաչափերով
-
Ճնշելով ֆոնային ծախսերը կոդավորման թարմացումների կառավարման հնարավորությունը
Անկախ PasswordEncoderFactories
օգտագործելուց կարող եք ստեղծել DelegatingPasswordEncoder
արտունի օրինակ:
PasswordEncoder passwordEncoder =
PasswordEncoderFactories.createDelegatingPasswordEncoder();
val passwordEncoder: PasswordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder()
Բացի այդ, դուք կարող եք ստեղծել ձեր սեփական պատճենը: Օրինակ:
String idForEncode = "bcrypt";
Map encoders = new HashMap<>();
encoders.put(idForEncode, new BCryptPasswordEncoder());
encoders.put("noop", NoOpPasswordEncoder.getInstance());
encoders.put("pbkdf2", new Pbkdf2PasswordEncoder());
encoders.put("scrypt", new SCryptPasswordEncoder());
encoders.put("sha256", new StandardPasswordEncoder());
PasswordEncoder passwordEncoder =
new DelegatingPasswordEncoder(idForEncode, encoders);
val idForEncode = "bcrypt"
val encoders: MutableMap<String, PasswordEncoder> = mutableMapOf()
encoders[idForEncode] = BCryptPasswordEncoder()
encoders["noop"] = NoOpPasswordEncoder.getInstance()
encoders["pbkdf2"] = Pbkdf2PasswordEncoder()
encoders["scrypt"] = SCryptPasswordEncoder()
encoders["sha256"] = StandardPasswordEncoder()
val passwordEncoder: PasswordEncoder = DelegatingPasswordEncoder(idForEncode, encoders)
Գախտնաբառների պահպանման ձևաչափ
Գախտնաբառի ընդհանուր ձևաչափը հետևյալն է:
{id}encodedPassword
Օրինակ, id
-ը օգտագործվող PasswordEncoder
-ի համար օգտագործվող նույնացուցիչն է, իսկ encodedPassword
-ը տվյալ PasswordEncoder
-ի համար սկզբնական կոդավորված գախտնաբառն է: id
-ը պետք է գտնվի գախտնաբառի սկզում, սկսվի {
ու ավարտվի }
նշաններով: Եթե id
-ը չի կարող գտնել, ապա id
-ն կունենա null արժեք: Օրինակ, ստորև ներկայացված է հնարավոր գախտնաբառերի ցուցակը, որոնք կոդավորված են տարբեր id
-ներով: Բոլոր սկզբնական գախտնաբառերը "password" են:
{bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG
{noop}password
{pbkdf2}5d923b44a6d129f3ddf3e3c8d29412723dcbde72445e8ef6bf3b508fbf17fa4ed4d6b99ca763d8dc
{scrypt}$e0801$8bWJaSu2IKSn9Z9kM+TPXfOc/9bdYSrN1oD9qfVThWEwdRTnO7re7Ei+fUZRJ68k9lTyuTeUp4of4g24hHnazw==$OAOec05+bXxvuu/1qZ6NUR+xQYvYv7BeL1QxwRpY5Pc=
{sha256}97cde38028ad898ebc02e690819fa220e88c62e0699403e94fff291cfffaf8410849f27605abcbc0
- Առաջին գախտնաբառի
PasswordEncoder
-ի նույնացուցիչը կունենաbcrypt
արժեք, իսկ կոդավորված գախտնաբառը կպատկերվի որպես$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG
: Համապատասխանության դեպքում այն կհանձնվիBCryptPasswordEncoder
- Երկրորդ գախտնաբառի
PasswordEncoder
-ի նույնացուցիչը կունենաnoop
արժեք, իսկ կոդավորված գախտնաբառը կպատկերվի որպեսpassword
: Համապատասխանության դեպքում այն կհանձնվիNoOpPasswordEncoder
- Երրորդ գախտնաբառի
PasswordEncoder
-ի նույնացուցիչը կունենաpbkdf2
արժեք, իսկ կոդավորված գախտնաբառը կպատկերվի որպես5d923b44a6d129f3ddf3e3c8d29412723dcbde72445e8ef6bf3b508fbf17fa4ed4d6b99ca763d8dc
: Համապատասխանության դեպքում այն կհանձնվիPbkdf2PasswordEncoder
- Չորրորդ գախտնաբառի
PasswordEncoder
-ի նույնացուցիչը կունենաscrypt
արժեք, իսկ կոդավորված գախտնաբառը կպատկերվի որպես$e0801$8bWJaSu2IKSn9Z9kM+TPXfOc/9bdYSrN1oD9qfVThWEwdRTnO7re7Ei+fUZRJ68k9lTyuTeUp4of4g24hHnazw==$OAOec05+bXxvuu/1qZ6NUR+xQYvYv7BeL1QxwRpY5Pc=
: Համապատասխանության դեպքում այն կհանձնվիSCryptPasswordEncoder
- Վերջնական գախտնաբառի
PasswordEncoder
-ի նույնացուցիչը կունենաsha256
արժեք, իսկ կոդավորված գախտնաբառը կպատկերվի որպես97cde38028ad898ebc02e690819fa220e88c62e0699403e94fff291cfffaf8410849f27605abcbc0
: Համապատասխանության դեպքում այն կհանձնվիStandardPasswordEncoder
Որոշ օգտատերեր կարող են անհանգստանալ, որ պահպանման ձևաչափը դրված է հնարավոր հաքերի համար: Այս մասին անհանգստանալու կարիք չկա, քանի որ գախտնաբառի պահպանումը կախված չէ նրանից, թե ալգորիթմը փակ է: Բացի այդ, մեծամասամբ ձևաչափերը չարագործը հեշտությամբ կկարողանա չկատարել և առանց քայլ-prefiksa: Օրինակ, BCrypt-գախտնաբառները հաճախ սկսվում են $2a$
:
Գախտնաբառի կոդավորում
Կոնստրուկտորին փոխանցված idForEncode
-ը որոշում է, թե որ PasswordEncoder
-ը կօգտագործվի գախտնաբառերի կոդավորման համար: Վերևում ստեղծված DelegatingPasswordEncoder
-ի դեպքում, սա նշանակում է, որ գախտնաբառի կոդավորման արդյունքը կփոխանցվի BCryptPasswordEncoder
-ին և կտրամադրվի {bcrypt}
նախածանցով: Վերջնական արդյունքը կլինի հետևյալը:
{bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG
Գախտնաբառի համընկնում
Համապատասխանությունը կատարվում է հիման վրա {id}
-ի և id
-ի վրա ցուցադրվող PasswordEncoder
-ի, որը նշված է կոնստրուկտորում: Լռելյայն matches(CharSequence, String)
հատկանիշի կանչման արդյունքում արդյունքը՝ գախտնաբառով և id
-ով, որը չի ցուցադրվել (ներառյալ null ճանաչանակիչը), կհանգեցնի IllegalArgumentException
: Այս աշխատանքի տրամաբանությունը կարելի է կարգավորել DelegatingPasswordEncoder.setDefaultPasswordEncoderForMatches(PasswordEncoder)
-ի միջոցով:
Օգտագործելով id
-ը, մենք կարող ենք համընկնել ցանկացած գախտնաբառի կոդավորման հետ, բայց կոդավորել գախտնաբառներ, օգտագործելով ամենաժամանակակից կոդավորման մեխանիզմ: Սա կարևոր է, քանի որ ի տարբերություն կոդավորման, գախտնաբառի հեշերն այնպիսին են, որ միակողմանի հեշը վերականգնել պարզ տեքստի չի կարող: Քանի որ հնարավոր չէ վերականգնել պարզ տեքստը, սա բարդացնում է գախտնաբառների տեղափոխումը: Չնայած օգտատերերը հեշտությամբ կարող են տեղափոխել NoOpPasswordEncoder
-ը, մենք որոշեցինք ավելացնել այն լռելյայն, որպեսզի հեշտ լինի սկսել աշխատանքը:
Սկսում ենք աշխատանք
Եթե դուք նախապատրաստում եք դեմո-տարբերակ կամ նմուշ, կարդալու ժամանակ ծախսելը գախտնաբառների հեշավորման համար կարող է մի փոքր դժվարություն լինել: Կան տարօրինակ մեխանիզմներ, որոնք նպաստում են այս խնդրի լուծմանը, բայց դրանք դեռ նախատեսված չեն արտադրական կատարողականության համար:
User user = User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("user")
.build();
System.out.println(user.getPassword());
// {bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG
val user = User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("user")
.build()
println(user.password)
// {bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG
Եթե դուք ստեղծում եք մի քանի օգտատերեր, դուք կարող եք նաև վերաօգտագործել կոնստրուկտորը:
UserBuilder users = User.withDefaultPasswordEncoder();
User user = users
.username("user")
.password("password")
.roles("USER")
.build();
User admin = users
.username("admin")
.password("password")
.roles("USER","ADMIN")
.build();
val users = User.withDefaultPasswordEncoder()
val user = users
.username("user")
.password("password")
.roles("USER")
.build()
val admin = users
.username("admin")
.password("password")
.roles("USER", "ADMIN")
.build()
Սա թույլ է տալիս հեշավորել պահվող գախտնաբառը, բայց գախտնաբառները դեռ բաց են ապարատում և հասարակ տեքստում են: Այսպիսով, այս մեթոդը դեռևս համարվում է որպես անվտանգ արտադրական կատարման պայմաններում: Արտադրական կատարման պայմաններում գախտնաբառները պետք է հեշավորվեն արտաքին միջավայրում:
Կոդավորում Spring Boot CLI-ի միջոցով
Գախտնաբառ ճիշտ կոդավորելու ամենապարզ միջոցը՝ օգտագործել Spring Boot CLI:
Օրինակ, հետևյալ հրահանգը կոդավորում է password
գախտնաբառը օգտագործման համար DelegatingPasswordEncoder-ում:
spring encodepassword password
{bcrypt}$2a$10$X5wFBtLrL/kHcmrOGGTrGufsBX8CJ0WpQpF3pgeuxBB/H73BK1DW6
Անբարեխիղճության վերացում
Հետևյալ սխալը տեղի է ունենում, եթե պահվող գախտնաբառներից մեկը չունի նույնացուցիչ:
java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null" at org.springframework.security.crypto.password.DelegatingPasswordEncoder$UnmappedIdPasswordEncoder.matches(DelegatingPasswordEncoder.java:233) at org.springframework.security.crypto.password.DelegatingPasswordEncoder.matches(DelegatingPasswordEncoder.java:196)
Սխալը շտկելու ամենապարզ տարբերակը՝ անցնել հստակորեն նշված PasswordEncoder
-ին, որով կոդավորվում են ձեր գախտնաբառները: Այս խնդիրը լուծելու ամենապարզ միջոցը՝ պարզել, թե ինչպես են ներկայումս պահվում ձեր գախտնաբառները, և հստակ նշել ճիշտ PasswordEncoder
-ը:
Եթե դուք տեղափոխվում եք Spring Security 4.2.x-ից, կարող եք վերադառնալ նախորդ աշխատանքի տրամաբանությանը բացելով NoOpPasswordEncoder
-ի bean-ը:
Բացի այդ, կարելի է բոլոր գախտնաբառներին հստակորեն նշված նույնացուցիչ տրամադրել և շարունակել օգտագործել DelegatingPasswordEncoder
-ը: Օրինակ՝ եթե դուք օգտագործում եք BCrypt, կարող եք տեղափոխել ձեր գախտնաբառը ինչ-որ բանից նման այս տեսքով:
$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG
դեպի
{bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG
Ողջ ցուցակը կարող եք գտնել PasswordEncoderFactories-ի Javadoc-ում:
BCryptPasswordEncoder
BCryptPasswordEncoder
-ի իրականացումը օգտագործում է լայնորեն աջակցվող bcrypt ալգորիթմը գախտնաբառերի հեշավորման համար: Այն ավելի դիմացկուն դարձնելու համար bcrypt-ը դիտավորությամբ դանդաղեցված է: Ինչպես այլ ադապտիվ հաշվարկային անհասանելի ֆունկցիները, այն պետք է նուրբ կազմաձևել այնպես, որպեսզի գախտնաբառի վալիդացիան ձեր համակարգով տևի մոտ 1 վայրկյան: BCryptPasswordEncoder
-ի լռելյայն իրականացումը օգտագործում է 10 վստահելիության պարամետր, ինչպես նշված է BCryptPasswordEncoder-ի Javadoc-ում: Առաջարկվում է կազմաձևել և փորձարկել ձեր համակարգում այնպես, որ գախտնաբառի վալիդացիան տևի մոտ 1 վայրկյան:
// Ստեղծում ենք կոդավորող 16 վստահելիության պարամետրով
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(16);
String result = encoder.encode("myPassword");
assertTrue(encoder.matches("myPassword", result));
// Ստեղծում ենք կոդավորող 16 վստահելիության պարամետրով
val encoder = BCryptPasswordEncoder(16)
val result: String = encoder.encode("myPassword")
assertTrue(encoder.matches("myPassword", result))
Argon2PasswordEncoder
Argon2PasswordEncoder
-ի իրականացումը օգտագործում է Argon2 ալգորիթմը գախտնաբառերի հեշավորման համար: Argon2-ը գախտնաբառերի հեշավորման մրցույթի հաղթողն է: Argon2-ը դիտավորությամբ դանդաղեցված է, իսկ համակարգի վրա առավել մեծ ծանրաբեռնվածություն պահանջում է: Ինչպես այլ ադապտիվ հաշվարկայի�� անհասանելի ֆունկցիներ, այն պետք է նուրբ կազմաձևել այնպես, որպեսզի գախտնաբառի վալիդացիան ձեր համակարգով տևի մոտ 1 վայրկյան: Զգուշանում է, որ Argon2PasswordEncoder
-ի ընթացիկ իրականացումը պահանջում է BouncyCastle:
// Ստեղծում ենք կոդավորող բոլոր լռելյայն կարգավորումներով
Argon2PasswordEncoder encoder = new Argon2PasswordEncoder();
String result = encoder.encode("myPassword");
assertTrue(encoder.matches("myPassword", result));
// Ստեղծում ենք կոդավորող բոլոր լռելյայն կարգավորումներով
val encoder = Argon2PasswordEncoder()
val result: String = encoder.encode("myPassword")
assertTrue(encoder.matches("myPassword", result))
Pbkdf2PasswordEncoder
Pbkdf2PasswordEncoder
-ի իրականացումը օգտագործում է PBKDF2 ալգորիթմը գախտնաբառերի հեշավորման համար: PBKDF2-ը դիտավորությամբ դանդաղեցված է: Ինչպես այլ ադապտիվ հաշվարկային անհասանելի ֆունկցիները, այն պետք է նուրբ կազմաձևել այնպես, որպեսզի գախտնաբառի վալիդացիան ձեր համակարգով տևի մոտ 1 վայրկյան: Այս ալգորիթմը հարմար է, եթե պահանջվում է FIPS վկայագրում:
// Ստեղծում ենք կոդավորող բոլոր լռելյայն կարգավորումներով
Pbkdf2PasswordEncoder encoder = new Pbkdf2PasswordEncoder();
String result = encoder.encode("myPassword");
assertTrue(encoder.matches("myPassword", result));
// Ստեղծում ենք կոդավորող բոլոր լռելյայն կարգավորումներով
val encoder = Pbkdf2PasswordEncoder()
val result: String = encoder.encode("myPassword")
assertTrue(encoder.matches("myPassword", result))
SCryptPasswordEncoder
SCryptPasswordEncoder
-ի իրականացումը օգտագործում է scrypt ալգորիթմը գախտնաբառերի հեշավորման համար: Ալգորիթմը դիտավորությամբ դանդաղեցված է, և այն պահանջում է մեծ հիշողություն: Ինչպես այլ ադապտիվ հաշվարկային անհասանելի ֆունկցիները, այն պետք է նուրբ կազմաձևել այնպես, որպեսզի գախտնաբառի վալիդացիան ձեր համակարգով տևի մոտ 1 վայրկյան:
// Ստեղծում ենք կոդավորող բոլոր լռելյայն կարգավորումներով
SCryptPasswordEncoder encoder = new SCryptPasswordEncoder();
String result = encoder.encode("myPassword");
assertTrue(encoder.matches("myPassword", result));
// Ստեղծում ենք կոդավորող բոլոր լռելյայն կարգավորումներով
val encoder = SCryptPasswordEncoder()
val result: String = encoder.encode("myPassword")
assertTrue(encoder.matches("myPassword", result))
Այլ PasswordEncoders
Ուղիղ հետնորդության համար կան մի շարք PasswordEncoder
-ի այլ իրականացումներ: Բոլորը հնացած են և չեն թույլատրում համարվել անվտանգ: Սակայն նախագծեր չկան դրանց հանման համար, քանի որ առկա նախորդ համակարգերի տեղափոխումը դժվար է:
Գախտնաբառերի պահեստավորման կազմաձևումը
Spring Security-ը ըստ լռելյայն օգտագործում է DelegatingPasswordEncoder: Սակայն սա կարելի է կարգավորել բացելով PasswordEncoder
-ը որպես Spring bean:
Եթե դուք տեղափոխվում եք Spring Security 4.2.x-ից, կնվաճեիք վերադառնալ նախորդ աշխատանքի տրամաբանությանը բացելով NoOpPasswordEncoder
-ի bean-ը:
Վերադառնալը NoOpPasswordEncoder
-ին անվտանգ չի համարվում: Փոխարենը պետք է անցնել DelegatingPasswordEncoder
-ի օգտագործման, որպեսզի ապահովվի գախտնաբառերի անվտանգ կոդավորումը:
@Bean
public static PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
<b:bean id="passwordEncoder"
class="org.springframework.security.crypto.password.NoOpPasswordEncoder" factory-method="getInstance"/>
@Bean
fun passwordEncoder(): PasswordEncoder {
return NoOpPasswordEncoder.getInstance();
}
XML կարգավորումը պահանջում է, որ NoOpPasswordEncoder
-ի bean-ի անունը լինի passwordEncoder
:
Գախտնաբառի կազմաձևման փոփոխություն
Մեծամասնության ծրագրերը, որոնք թույլ են տալիս օգտատիրոջին սահմանել գախտնաբառ, պահանջում են նաև գախտնաբառի թարմացման ֆունկցիա:
Լայնորեն օգտագործվող գախտնաբառի փոփոխման URL-ն նշում է մեխանիզմը, որով գախտնաբառի կառավարման գործիքները կարող են նկատել կոնկրետ հավելվածի համար գախտնաբառի թարմացման վերջնակետը:
Դուք կարող եք կարգավորել Spring Security-ը այդ հանգրվանի որոշման վերջնակետի փոխանցման համար: Օրինակ, եթե ձեր հավելվածի գախտնաբառի փոփոխման վերջնակետը /change-password
է, այն ժամանակ կարելի է կարգավորել Spring Security-ն այսպես:
http
.passwordManagement(Customizer.withDefaults())
<sec:password-management/>
http {
passwordManagement { }
}
Հետո, երբ գախտնաբառի կառավարիչը անցնի /.well-known/change-password
հասցեով, Spring Security-ն ուղղորդելու է ձեր վերջնակետին՝ /change-password
:
Կամ էլ, եթե ձեր վերջնակետը /change-password
չէ, այն կարելի է սահմանել այսպես:
http
.passwordManagement((management) -> management
.changePasswordPage("/update-password")
)
<sec:password-management change-password-page="/update-password"/>
http {
passwordManagement {
changePasswordPage = "/update-password"
}
}
Այսքանում, երբ գախտնաբառի կառավարիչը անցնի /.well-known/change-password
հասցեով, Spring Security-ն ուղղորդելու է դեպի /update-password
:
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ