JavaRush /Java блогу /Random-KY /Javaдагы коопсуздук: мыкты тажрыйбалар
Roman Beekeeper
Деңгээл

Javaдагы коопсуздук: мыкты тажрыйбалар

Группада жарыяланган
Сервердик тиркемелерде эң маанилүү көрсөткүчтөрдүн бири коопсуздук болуп саналат. Бул Функционалдык эмес талаптардын түрлөрүнүн бири . Javaдагы коопсуздук: мыкты тажрыйбалар - 1Коопсуздук көптөгөн компоненттерден турат. Албетте, белгилүү болгон бардык коргоо принциптерин жана аракеттерин толук камтуу үчүн бир нече макала жазуу керек, андыктан эң негизгилерине токтололу. Бул теманы жакшы билген адам бардык процесстерди орното алат жана алар жаңы коопсуздук тешиктерин түзбөсүн камсыздай алат, ар бир командага керек болот. Албетте, бул ыкмаларды аткарсаңыз, колдонмо толугу менен коопсуз болот деп ойлобошуңуз керек. Жок! Бирок алар менен, албетте, коопсуз болот. Go.

1. Java тил деңгээлинде коопсуздукту камсыз кылыңыз

Биринчиден, Javaдагы коопсуздук тилдин өзгөчөлүгү деңгээлинен башталат. Мүмкүнчүлүктү өзгөрткүчтөр болбосо, биз эмне кылмакпыз?... Анархия, андан кем эмес. Программалоо тor бизге коопсуз codeду жазууга жардам берет жана ошондой эле көптөгөн жашыруун коопсуздук мүмкүнчүлүктөрүнөн пайдалана алат:
  1. Күчтүү терүү. Java бул статикалык түрдө терилген тил, ал иштөө учурунда каталарды аныктоо мүмкүнчүлүгүн берет.
  2. Кирүү модификаторлору. Алардын жардамы менен биз класстарга, методдорго жана класс талааларына кирүү мүмкүнчүлүгүн конфигурациялай алабыз.
  3. Автоматтык эстутум башкаруу. Бул үчүн, бизде (Javaists ;)) сизди кол менен конфигурациялоодон бошоткон таштанды жыйноочу бар. Ооба, кээде көйгөйлөр пайда болот.
  4. Байтcodeду текшерүү: Java byte-codeго түзүлөт, аны иштетүүдөн мурун иштөө убактысы менен текшерилет .
Башка нерселер менен катар, коопсуздук боюнча Oracle сунуштары бар . Албетте, ал "жогорку стилде" жазылган эмес жана аны окуп жатканда бир нече жолу уктап калышы мүмкүн, бирок бул татыктуу. Коопсуз codeду кантип жазуу керектиги боюнча кеңештерди берген Java SE үчүн Коопсуз codeдоо көрсөтмөлөрү өзгөчө маанилүү document болуп саналат . Бул document көптөгөн пайдалуу маалыматтарды камтыйт. Мүмкүн болсо, албетте, окууга арзыйт. Бул материалга кызыгууну жаратуу үчүн, бул жерде кээ бир кызыктуу кеңештер бар:
  1. Коопсуз сезгич класстарды сериялаштыруудан качыңыз. Бул учурда, класс интерфейсин сериялаштырылган файлдан ала аласыз, сериялаштырылган маалыматтарды айтпаганда да.
  2. Өзгөрүүчү маалымат класстарынан качууга аракет кылыңыз. Бул өзгөрүлгүс класстардын бардык артыкчылыктарын берет (мисалы, жиптин коопсуздугу). Эгерде өзгөрүлүүчү an object болсо, бул күтүлбөгөн жүрүм-турумга алып келиши мүмкүн.
  3. Кайтарылган өзгөрүлүүчү an objectтердин көчүрмөсүн жасаңыз. Эгерде метод ички өзгөрүлүүчү an objectке шилтемени кайтарса, анда кардар codeу an objectтин ички абалын өзгөртө алат.
  4. Жана башка…
Жалпысынан алганда, Java SE үчүн Коопсуз codeдоо көрсөтмөлөрү Java тorнде codeду кантип туура жана коопсуз жазуу боюнча кеңештерди жана ыкмаларды камтыйт.

2. SQL инъекциясынын аялуулугун жок кылыңыз

Уникалдуу алсыздык. Анын уникалдуулугу бул эң атактуу жана эң кеңири таралган кемчorктердин бири экендигинде. Эгер сизди коопсуздук маселеси кызыктырбаса, анда ал жөнүндө билбей каласыз. SQL инъекциясы деген эмне? Бул күтүлбөгөн жерде кошумча SQL codeун киргизүү аркылуу маалымат базасына чабуул. Бизде маалымат базасын суроо үчүн кандайдыр бир параметрди алган ыкма бар дейли. Мисалы, колдонуучунун аты. Алсыздыгы бар code төмөнкүдөй көрүнөт:
// Метод достает из базы данных всех пользователей с определенным именем
public List<User> findByFirstName(String firstName) throws SQLException {
   // Создается связь с базой данных
   Connection connection = DriverManager.getConnection(DB_URL, USER, PASS);

   // Пишем sql request в базу данных с нашим firstName
   String query = "SELECT * FROM USERS WHERE firstName = " + firstName;

   // выполняем request
   Statement statement = connection.createStatement();
   ResultSet result = statement.executeQuery(query);

   // при помощи mapToUsers переводит ResultSet в коллекцию юзеров.
   return mapToUsers(result);
}

private List<User> mapToUsers(ResultSet resultSet) {
   //переводит в коллекцию юзеров
}
Бул мисалда sql сурамы өзүнчө сапта алдын ала даярдалган. Маселе эмнеде экени көрүнүп турат, туурабы? Балким, көйгөй аны колдонуу жакшыраак болот String.format? Жок? Анда эмне? Келгиле, өзүбүздү тестиердин ордуна коюп, баалуулукта эмнени жеткирүүгө болорун ойлонолу firstName. Мисалы:
  1. Сиз күтүлгөн нерсени өткөрө аласыз - колдонуучунун аты. Андан кийин маалымат базасы ошол ат менен бардык колдонуучуларды кайтарып берет.
  2. Сиз бош сапты өткөрө аласыз: анда бардык колдонуучулар кайтарылат.
  3. Же төмөндөгүлөрдү өткөрө аласыз: “''; ТАПКАН ТАБЛИЦИ КОЛДОНУУЧУЛАР;”. Ал эми бул жерде дагы чоң көйгөйлөр болот. Бул суроо tableны маалымат базасынан алып салат. Бардык маалыматтар менен. БАРДЫК.
Бул кандай көйгөйлөргө алып келиши мүмкүн экенин элестете аласызбы? Андан кийин каалаганыңызды жаза аласыз. Сиз бардык колдонуучулардын атын өзгөртө аласыз, алардын даректерин өчүрө аласыз. Саботаждын масштабы абдан чоң. Буга жол бербөө үчүн, сиз даяр суроону инъекциялоону токтотуп, анын ордуна параметрлерди колдонуп түзүшүңүз керек. Бул маалымат базасын суроо үчүн бир гана жолу болушу керек. Ушундай жол менен сиз бул кемчorкти жок кыла аласыз. Мисал:
// Метод достает из базы данных всех пользователей с определенным именем
public List<User> findByFirstName(String firstName) throws SQLException {
   // Создается связь с базой данных
   Connection connection = DriverManager.getConnection(DB_URL, USER, PASS);

   // Создаем параметризированный request.
   String query = "SELECT * FROM USERS WHERE firstName = ?";

   // Создаем подготовленный стейтмент с параметризованным requestом
   PreparedStatement statement = connection.prepareStatement(query);

   // Передаем meaning параметра
   statement.setString(1, firstName);

   // выполняем request
   ResultSet result = statement.executeQuery(query);

   // при помощи mapToUsers переводим ResultSet в коллекцию юзеров.
   return mapToUsers(result);
}

private List<User> mapToUsers(ResultSet resultSet) {
   //переводим в коллекцию юзеров
}
Бул жол менен бул алсыздыктын алдын алат. Бул макалага караганда маселеге тереңирээк киришүүнү каалагандар үчүн бул жерде сонун мисал . Бул бөлүгүн түшүнгөнүңүздү кантип билесиз? Эгерде төмөндөгү тамаша айкын болуп калса, анда бул аялуулуктун маңызы айкын экендигинин ишенимдүү белгиси :D Javaдагы коопсуздук: мыкты тажрыйбалар - 2

3. Көз карандылыктарды скандоо жана жаңыртуу

Бул эмнени билдирет? Көз карандылык деген эмне экенин билбегендер үчүн мен түшүндүрүп берем: бул башка бирөөнүн чечимин кайра колдонуу үчүн автоматтык куруу системаларын (Maven, Gradle, Ant) колдонуу менен долбоорго туташтырылган codeу бар банка архиви. Мисалы, Project Lombok , ал иштеп жаткан учурда биз үчүн алуучуларды, орнотууларды ж.б. Ал эми чоң тиркемелер жөнүндө айтсак, алар ар кандай көз карандылыктарды колдонушат. Кээ бирлери өтмө (башкача айтканда, ар бир көз карандылыктын өзүнүн көз карандылыгы болушу мүмкүн жана башкалар). Ошондуктан, чабуулчулар ачык булактан көз карандылыкка көбүрөөк көңүл буруп жатышат, анткени алар дайыма колдонулуп, көптөгөн кардарлар үчүн көйгөйлөрдү жаратышы мүмкүн. Бүткүл көз карандылык дарагында белгилүү алсыздыктар жок экенине ынануу маанилүү (бул так ошондой көрүнөт). Жана муну жасоонун бир нече жолу бар.

Мониторинг үчүн Snyk колдонуңуз

Snyk куралы бардык долбоордун көз карандылыгын текшерет жана белгилүү кемчorктерди белгилейт. Ал жерде, мисалы, GitHub аркылуу долбоорлоруңузду каттап, импорттой аласыз. Javaдагы коопсуздук: мыкты тажрыйбалар - 3Ошондой эле, жогорудагы сүрөттөн көрүнүп тургандай, эгер жаңыраак versionда бул алсыздыктын чечими бар болсо, Snyk муну сунуштап, Pull-Request түзүүнү сунуштайт. Аны ачык булактуу долбоорлор үчүн бекер колдонсо болот. Долбоорлор кандайдыр бир жыштыкта ​​сканерден өткөрүлөт: жумасына бир жолу, айына бир жолу. Мен катталып, бардык коомдук репозиторийлеримди Snyk сканерине коштум (бул жерде коркунучтуу эч нерсе жок: алар бардыгы үчүн ачык). Андан кийин, Snyk сканерлөөнүн жыйынтыгын көрсөттү: Javaдагы коопсуздук: мыкты тажрыйбалар - 4Жана бир аздан кийин, Snyk-бот көз карандылыкты жаңыртуу керек болгон долбоорлордо бир нече Pull-Requests даярдады: Javaдагы коопсуздук: мыкты тажрыйбалар - 5Жана дагы бир нерсе: Javaдагы коопсуздук: мыкты тажрыйбалар - 6Демек, бул аялуу жерлерди издөө жана жаңыртууга мониторинг жүргүзүү үчүн эң сонун курал. жаңы versionлар.

GitHub коопсуздук лабораториясын колдонуңуз

GitHubда иштегендер өздөрүнүн орнотулган куралдарынан да пайдалана алышат. Бул ыкма жөнүндө көбүрөөк GitHub Security Lab блогунан менин котормомдон окуй аласыз . Бул курал, албетте, Snyk караганда жөнөкөй, бирок, албетте, аны көз жаздымда калтырбоо керек. Мындан тышкары, белгилүү алсыздыктардын саны өсө берет, ошондуктан Snyk жана GitHub Security Lab да кеңейип, жакшырат.

Sonatype DepShield иштетүү

Эгер сиз репозиторийлериңизди сактоо үчүн GitHub колдонсоңуз, анда MarketPlace - Sonatype DepShieldден долбоорлоруңузга тиркемелердин бирин кошо аласыз. Анын жардамы менен, сиз ошондой эле көз карандылык үчүн долбоорлорду сканерлей аласыз. Андан тышкары, эгерде ал бир нерсе тапса, төмөндө көрсөтүлгөндөй, GitHub маселеси тиешелүү сыпаттамасы менен түзүлөт: Javaдагы коопсуздук: мыкты тажрыйбалар - 7

4. Купуя маалыматтарды этияттык менен колдонуңуз

Javaдагы коопсуздук: мыкты тажрыйбалар - 8Англис тorнде сүйлөөдө "сезимдүү маалыматтар" деген сөз айкашы көбүрөөк кездешет. Кардардын жеке маалыматтарын, кредиттик карталардын номерлерин жана башка жеке маалыматтарын ачыкка чыгаруу орду толгус зыян келтириши мүмкүн. Биринчиден, сиз тиркеменин дизайнын кылдат карап чыгып, кандайдыр бир маалымат чындыгында керек экендигин аныкташыңыз керек. Балким, алардын айрымдарынын кереги жоктур, бирок келе элек жана келээри күмөндүү келечек үчүн кошулган. Мындан тышкары, долбоорлорду каттоо учурунда, мындай маалыматтар агып кетиши мүмкүн. toString()Купуя маалыматтардын журналдарыңызга кирүүсүн алдын алуунун жөнөкөй жолу - бул домен an objectтеринин ыкмаларын (мисалы, Колдонуучу, Студент, Мугалим ж.б.) тазалоо . Бул сезимтал талаалардын кокустан басылып чыгышын алдын алат. Эгерде сиз Lombok ыкмасын жаратуу үчүн колдонсоңуз , анда талааны ыкма аркылуу чыгарууда колдонууга жол бербөө үчүн toString()annotationны колдонсоңуз болот . Ошондой эле тышкы дүйнө менен маалыматтарды бөлүшүүдө өтө этият болуңуз. Мисалы, бардык колдонуучулардын аттарын көрсөткөн http акыркы чекити бар. Колдонуучунун ички уникалдуу идентификаторун көрсөтүүнүн кереги жок. Неге? Анткени аны колдонуу менен чабуулчу ар бир колдонуучу тууралуу башка, бир кыйла купуя маалыматты ала алат. Мисалы, сиз POJOларды JSONге сериялаштыруу жана сериядан чыгаруу үчүн Джексонду колдонсоңуз, белгилүү талааларды сериялаштыруудан жана сериядан чыгаруудан алдын алуу үчүн жана annotationларын колдоно аласыз . Жалпысынан алганда, ар кандай жерлер үчүн ар кандай POJO класстарын колдонушуңуз керек. Бул эмнени билдирет? @ToString.ExcludetoString()@JsonIgnore@JsonIgnoreProperties
  1. Маалыматтар базасы менен иштөө үчүн POJO - Entity гана колдонуңуз.
  2. Бизнес логикасы менен иштөө үчүн Объектти моделге өткөрүңүз.
  3. Тышкы дүйнө менен иштөө жана http суроо-талаптарын жөнөтүү үчүн үчүнчү жактарды - DTO колдонуңуз.
Ушундай жол менен сиз кайсы талаалар сырттан көрүнүп, кайсынысы көрүнбөй турганын так аныктай аласыз.

Күчтүү шифрлөө жана хэширлөө алгоритмдерин колдонуңуз

Кардардын купуя маалыматтары коопсуз сакталышы керек. Бул үчүн сиз шифрлөөнү колдонушуңуз керек. Тапшырмага жараша, сиз шифрлөөнүн кандай түрүн колдонууну чечишиңиз керек. Андан тышкары, күчтүүрөөк шифрлөө көбүрөөк убакытты талап кылат, андыктан ага болгон муктаждык ага сарпталган убакытты канчалык актаарын дагы бир жолу эске алуу керек. Албетте, алгоритмди өзүңүз жазсаңыз болот. Бирок бул керексиз. Сиз бул чөйрөдө болгон чечимдерди колдоно аласыз. Мисалы, Google Tink :
<!-- https://mvnrepository.com/artifact/com.google.crypto.tink/tink -->
<dependency>
   <groupId>com.google.crypto.tink</groupId>
   <artifactId>tink</artifactId>
   <version>1.3.0</version>
</dependency>
Келгиле, аны кантип колдонууну карап көрөлү, мисалы, бир жолду жана башканы кантип шифрлөө керек:
private static void encryptDecryptExample() {
   AeadConfig.register();
   KeysetHandle handle = KeysetHandle.generateNew(AeadKeyTemplates.AES128_CTR_HMAC_SHA256);

   String plaintext = "Цой жив!";
   String aad = "Юрий Клинских";

   Aead aead = handle.getPrimitive(Aead.class);
   byte[] encrypted = aead.encrypt(plaintext.getBytes(), aad.getBytes());
   String encryptedString = Base64.getEncoder().encodeToString(encrypted);
   System.out.println(encryptedString);

   byte[] decrypted = aead.decrypt(Base64.getDecoder().decode(encrypted), aad.getBytes());
   System.out.println(new String(decrypted));
}

Сырсөздү шифрлөө

Бул тапшырма үчүн ассиметриялык шифрлөөнү колдонуу эң коопсуз. Неге? Анткени колдонмо чындыгында сырсөздөрдү кайра чечүүнүн кереги жок. Бул жалпы мамиле болуп саналат. Чындыгында, колдонуучу сырсөздү киргизгенде, система аны шифрлейт жана сырсөз сактагычындагы менен салыштырат. Шифрлөө ошол эле каражаттардын жардамы менен ишке ашырылат, ошондуктан сиз алардын дал келишин күтө аласыз (эгер сиз туура сырсөздү киргизсеңиз; албетте). Бул максат үчүн BCrypt жана SCrypt ылайыктуу. Экөө тең бир тараптуу функциялар (криптографиялык хэштер), көп убакытты талап кылган эсептөө татаал алгоритмдери. Бул сизге керек болгон нерсе, анткени аны чечмелөө түбөлүккө созулат. Мисалы, Spring Security бир катар алгоритмдерди колдойт. SCryptPasswordEncoderСиз ошондой эле колдоно аласыз BCryptPasswordEncoder. Азыр күчтүү шифрлөө алгоритми кийинки жылы алсыз болушу мүмкүн. Жыйынтыгында колдонулган алгоритмдерди текшерип, китепканаларды алгоритмдер менен жаңылоо зарыл деген тыянакка келдик.

чыгаруунун ордуна

Бүгүн биз коопсуздук тууралуу сүйлөштүк жана, албетте, көп нерселер көшөгө артында калды. Мен жаңы эле сага жаңы дүйнөнүн эшигин ачтым: өз жашоосун жашаган дүйнө. Коопсуздук менен саясат менен бирдей: сен саясат менен алектенбесең, саясат сени менен алектенет. Салт боюнча, мен өзүмдүн Github аккаунтума жазылууну сунуштайм . Ал жерде мен окуп, жумушта колдонгон ар кандай технологиялар боюнча эмгектеримди жарыялайм.

пайдалуу шилтемелер

Ооба, сайтта дээрлик бардык макалалар англис тorнде жазылган. Каалайбызбы, каалабайбызбы, англис тor программисттер үчүн баарлаша турган тил. Программалоо боюнча бардык жаңы макалалар, китептер жана журналдар англис тorнде жазылган. Ошондуктан менин сунуштарга шилтемелерим көбүнчө англис тorнде:
  1. Habr: Жаңы баштагандар үчүн SQL инъекциясы
  2. Oracle: Java коопсуздук ресурстук борбору
  3. Oracle: Java SE үчүн коопсуз codeдоо көрсөтмөлөрү
  4. Baeldung: Java коопсуздук негиздери
  5. Орточо: Java коопсуздугуңузду күчөтүү үчүн 10 кеңеш
  6. Snyk: Java коопсуздугу боюнча 10 мыкты тажрыйба
  7. JR: GitHub коопсуздук лабораториясынын жарыясы: бардык codeуңузду чогуу коргоо
Комментарийлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION