JavaRush /Курсы /All lectures for AM purposes /Authentication-ի Ներածություն

Authentication-ի Ներածություն

All lectures for AM purposes
1 уровень , 673 лекция
Открыта

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 արտունի օրինակ:

DelegatingPasswordEncoder-ի ստեղծումը ըստ լռելյայն
Java
PasswordEncoder passwordEncoder =
    PasswordEncoderFactories.createDelegatingPasswordEncoder();
Kotlin
val passwordEncoder: PasswordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder()

Բացի այդ, դուք կարող եք ստեղծել ձեր սեփական պատճենը: Օրինակ:

Կաստոմային DelegatingPasswordEncoder-ի ստեղծումը
Java
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);
Kotlin
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)

Գախտնաբառների պահպանման ձևաչափ

Գախտնաբառի ընդհանուր ձևաչափը հետևյալն է:

DelegatingPasswordEncoder-ի պահպանման ձևաչափը
{id}encodedPassword

Օրինակ, id-ը օգտագործվող PasswordEncoder-ի համար օգտագործվող նույնացուցիչն է, իսկ encodedPassword-ը տվյալ PasswordEncoder-ի համար սկզբնական կոդավորված գախտնաբառն է: id-ը պետք է գտնվի գախտնաբառի սկզում, սկսվի { ու ավարտվի } նշաններով: Եթե id-ը չի կարող գտնել, ապա id-ն կունենա null արժեք: Օրինակ, ստորև ներկայացված է հնարավոր գախտնաբառերի ցուցակը, որոնք կոդավորված են տարբեր id-ներով: Բոլոր սկզբնական գախտնաբառերը "password" են:

DelegatingPasswordEncoder-ի միջոցով կոդավորված գախտնաբառերի օրինակ
{bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG 
{noop}password 
{pbkdf2}5d923b44a6d129f3ddf3e3c8d29412723dcbde72445e8ef6bf3b508fbf17fa4ed4d6b99ca763d8dc 
{scrypt}$e0801$8bWJaSu2IKSn9Z9kM+TPXfOc/9bdYSrN1oD9qfVThWEwdRTnO7re7Ei+fUZRJ68k9lTyuTeUp4of4g24hHnazw==$OAOec05+bXxvuu/1qZ6NUR+xQYvYv7BeL1QxwRpY5Pc=  
{sha256}97cde38028ad898ebc02e690819fa220e88c62e0699403e94fff291cfffaf8410849f27605abcbc0 
  1. Առաջին գախտնաբառի PasswordEncoder-ի նույնացուցիչը կունենա bcrypt արժեք, իսկ կոդավորված գախտնաբառը կպատկերվի որպես $2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG: Համապատասխանության դեպքում այն կհանձնվի BCryptPasswordEncoder
  2. Երկրորդ գախտնաբառի PasswordEncoder-ի նույնացուցիչը կունենա noop արժեք, իսկ կոդավորված գախտնաբառը կպատկերվի որպես password: Համապատասխանության դեպքում այն կհանձնվի NoOpPasswordEncoder
  3. Երրորդ գախտնաբառի PasswordEncoder-ի նույնացուցիչը կունենա pbkdf2 արժեք, իսկ կոդավորված գախտնաբառը կպատկերվի որպես 5d923b44a6d129f3ddf3e3c8d29412723dcbde72445e8ef6bf3b508fbf17fa4ed4d6b99ca763d8dc: Համապատասխանության դեպքում այն կհանձնվի Pbkdf2PasswordEncoder
  4. Չորրորդ գախտնաբառի PasswordEncoder-ի նույնացուցիչը կունենա scrypt արժեք, իսկ կոդավորված գախտնաբառը կպատկերվի որպես $e0801$8bWJaSu2IKSn9Z9kM+TPXfOc/9bdYSrN1oD9qfVThWEwdRTnO7re7Ei+fUZRJ68k9lTyuTeUp4of4g24hHnazw==$OAOec05+bXxvuu/1qZ6NUR+xQYvYv7BeL1QxwRpY5Pc=: Համապատասխանության դեպքում այն կհանձնվի SCryptPasswordEncoder
  5. Վերջնական գախտնաբառի PasswordEncoder-ի նույնացուցիչը կունենա sha256 արժեք, իսկ կոդավորված գախտնաբառը կպատկերվի որպես 97cde38028ad898ebc02e690819fa220e88c62e0699403e94fff291cfffaf8410849f27605abcbc0: Համապատասխանության դեպքում այն կհանձնվի StandardPasswordEncoder

Որոշ օգտատերեր կարող են անհանգստանալ, որ պահպանման ձևաչափը դրված է հնարավոր հաքերի համար: Այս մասին անհանգստանալու կարիք չկա, քանի որ գախտնաբառի պահպանումը կախված չէ նրանից, թե ալգորիթմը փակ է: Բացի այդ, մեծամասամբ ձևաչափերը չարագործը հեշտությամբ կկարողանա չկատարել և առանց քայլ-prefiksa: Օրինակ, BCrypt-գախտնաբառները հաճախ սկսվում են $2a$:

Գախտնաբառի կոդավորում

Կոնստրուկտորին փոխանցված idForEncode-ը որոշում է, թե որ PasswordEncoder-ը կօգտագործվի գախտնաբառերի կոդավորման համար: Վերևում ստեղծված DelegatingPasswordEncoder-ի դեպքում, սա նշանակում է, որ գախտնաբառի կոդավորման արդյունքը կփոխանցվի BCryptPasswordEncoder-ին և կտրամադրվի {bcrypt} նախածանցով: Վերջնական արդյունքը կլինի հետևյալը:

DelegatingPasswordEncoder-ի միջոցով կոդավորման օրինակ
{bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG

Գախտնաբառի համընկնում

Համապատասխանությունը կատարվում է հիման վրա {id}-ի և id-ի վրա ցուցադրվող PasswordEncoder-ի, որը նշված է կոնստրուկտորում: Լռելյայն matches(CharSequence, String) հատկանիշի կանչման արդյունքում արդյունքը՝ գախտնաբառով և id-ով, որը չի ցուցադրվել (ներառյալ null ճանաչանակիչը), կհանգեցնի IllegalArgumentException: Այս աշխատանքի տրամաբանությունը կարելի է կարգավորել DelegatingPasswordEncoder.setDefaultPasswordEncoderForMatches(PasswordEncoder)-ի միջոցով:

Օգտագործելով id-ը, մենք կարող ենք համընկնել ցանկացած գախտնաբառի կոդավորման հետ, բայց կոդավորել գախտնաբառներ, օգտագործելով ամենաժամանակակից կոդավորման մեխանիզմ: Սա կարևոր է, քանի որ ի տարբերություն կոդավորման, գախտնաբառի հեշերն այնպիսին են, որ միակողմանի հեշը վերականգնել պարզ տեքստի չի կարող: Քանի որ հնարավոր չէ վերականգնել պարզ տեքստը, սա բարդացնում է գախտնաբառների տեղափոխումը: Չնայած օգտատերերը հեշտությամբ կարող են տեղափոխել NoOpPasswordEncoder-ը, մենք որոշեցինք ավելացնել այն լռելյայն, որպեսզի հեշտ լինի սկսել աշխատանքը:

Սկսում ենք աշխատանք

Եթե դուք նախապատրաստում եք դեմո-տարբերակ կամ նմուշ, կարդալու ժամանակ ծախսելը գախտնաբառների հեշավորման համար կարող է մի փոքր դժվարություն լինել: Կան տարօրինակ մեխանիզմներ, որոնք նպաստում են այս խնդրի լուծմանը, բայց դրանք դեռ նախատեսված չեն արտադրական կատարողականության համար:

Пример withDefaultPasswordEncoder
Java
User user = User.withDefaultPasswordEncoder()
  .username("user")
  .password("password")
  .roles("user")
  .build();
System.out.println(user.getPassword());
// {bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG
Kotlin
val user = User.withDefaultPasswordEncoder()
    .username("user")
    .password("password")
    .roles("user")
    .build()
println(user.password)
// {bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG

Եթե դուք ստեղծում եք մի քանի օգտատերեր, դուք կարող եք նաև վերաօգտագործել կոնստրուկտորը:

withDefaultPasswordEncoder, որը վերաօգտագործում է կոնստրուկտորը
Java
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();
Kotlin
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 Boot CLI-ի միջոցով encodepassword հրամանատարի օգտագործման օրինակ
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 վայրկյան:

BCryptPasswordEncoder
Java
// Ստեղծում ենք կոդավորող 16 վստահելիության պարամետրով
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(16);
String result = encoder.encode("myPassword");
assertTrue(encoder.matches("myPassword", result));
Kotlin
// Ստեղծում ենք կոդավորող 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
Java
// Ստեղծում ենք կոդավորող բոլոր լռելյայն կարգավորումներով
Argon2PasswordEncoder encoder = new Argon2PasswordEncoder();
String result = encoder.encode("myPassword");
assertTrue(encoder.matches("myPassword", result));
Kotlin
// Ստեղծում ենք կոդավորող բոլոր լռելյայն կարգավորումներով
val encoder = Argon2PasswordEncoder()
val result: String = encoder.encode("myPassword")
assertTrue(encoder.matches("myPassword", result))

Pbkdf2PasswordEncoder

Pbkdf2PasswordEncoder-ի իրականացումը օգտագործում է PBKDF2 ալգորիթմը գախտնաբառերի հեշավորման համար: PBKDF2-ը դիտավորությամբ դանդաղեցված է: Ինչպես այլ ադապտիվ հաշվարկային անհասանելի ֆունկցիները, այն պետք է նուրբ կազմաձևել այնպես, որպեսզի գախտնաբառի վալիդացիան ձեր համակարգով տևի մոտ 1 վայրկյան: Այս ալգորիթմը հարմար է, եթե պահանջվում է FIPS վկայագրում:

Pbkdf2PasswordEncoder
Java
// Ստեղծում ենք կոդավորող բոլոր լռելյայն կարգավորումներով
Pbkdf2PasswordEncoder encoder = new Pbkdf2PasswordEncoder();
String result = encoder.encode("myPassword");
assertTrue(encoder.matches("myPassword", result));
Kotlin
// Ստեղծում ենք կոդավորող բոլոր լռելյայն կարգավորումներով
val encoder = Pbkdf2PasswordEncoder()
val result: String = encoder.encode("myPassword")
assertTrue(encoder.matches("myPassword", result))

SCryptPasswordEncoder

SCryptPasswordEncoder-ի իրականացումը օգտագործում է scrypt ալգորիթմը գախտնաբառերի հեշավորման համար: Ալգորիթմը դիտավորությամբ դանդաղեցված է, և այն պահանջում է մեծ հիշողություն: Ինչպես այլ ադապտիվ հաշվարկային անհասանելի ֆունկցիները, այն պետք է նուրբ կազմաձևել այնպես, որպեսզի գախտնաբառի վալիդացիան ձեր համակարգով տևի մոտ 1 վայրկյան:

SCryptPasswordEncoder
Java
// Ստեղծում ենք կոդավորող բոլոր լռելյայն կարգավորումներով
SCryptPasswordEncoder encoder = new SCryptPasswordEncoder();
String result = encoder.encode("myPassword");
assertTrue(encoder.matches("myPassword", result));
Kotlin
// Ստեղծում ենք կոդավորող բոլոր լռելյայն կարգավորումներով
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-ի օգտագործման, որպեսզի ապահովվի գախտնաբառերի անվտանգ կոդավորումը:

NoOpPasswordEncoder
Java
@Bean
public static PasswordEncoder passwordEncoder() {
    return NoOpPasswordEncoder.getInstance();
}
XML
<b:bean id="passwordEncoder"
        class="org.springframework.security.crypto.password.NoOpPasswordEncoder" factory-method="getInstance"/>
Kotlin
@Bean
fun passwordEncoder(): PasswordEncoder {
    return NoOpPasswordEncoder.getInstance();
}

XML կարգավորումը պահանջում է, որ NoOpPasswordEncoder-ի bean-ի անունը լինի passwordEncoder:

Գախտնաբառի կազմաձևման փոփոխություն

Մեծամասնության ծրագրերը, որոնք թույլ են տալիս օգտատիրոջին սահմանել գախտնաբառ, պահանջում են նաև գախտնաբառի թարմացման ֆունկցիա:

Լայնորեն օգտագործվող գախտնաբառի փոփոխման URL-ն նշում է մեխանիզմը, որով գախտնաբառի կառավարման գործիքները կարող են նկատել կոնկրետ հավելվածի համար գախտնաբառի թարմացման վերջնակետը:

Դուք կարող եք կարգավորել Spring Security-ը այդ հանգրվանի որոշման վերջնակետի փոխանցման համար: Օրինակ, եթե ձեր հավելվածի գախտնաբառի փոփոխման վերջնակետը /change-password է, այն ժամանակ կարելի է կարգավորել Spring Security-ն այսպես:

Գախտնաբառի փոփոխման լռելյայն վերջնակետը
Java
http
    .passwordManagement(Customizer.withDefaults())
XML
<sec:password-management/>
Kotlin
http {
    passwordManagement { }
}

Հետո, երբ գախտնաբառի կառավարիչը անցնի /.well-known/change-password հասցեով, Spring Security-ն ուղղորդելու է ձեր վերջնակետին՝ /change-password:

Կամ էլ, եթե ձեր վերջնակետը /change-password չէ, այն կարելի է սահմանել այսպես:

Գախտնաբառի փոփոխման վերջնակետ
Java
http
    .passwordManagement((management) -> management
        .changePasswordPage("/update-password")
    )
XML
<sec:password-management change-password-page="/update-password"/>
Kotlin
http {
    passwordManagement {
        changePasswordPage = "/update-password"
    }
}

Այսքանում, երբ գախտնաբառի կառավարիչը անցնի /.well-known/change-password հասցեով, Spring Security-ն ուղղորդելու է դեպի /update-password:

Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ