Spring Boot එකේ Password ආරක්ෂා කරමු: BCryptPasswordEncoder SC Guide

කොහොමද යාලුවනේ! Spring Boot එකේ Password ආරක්ෂාව තර කරමු - BCryptPasswordEncoder සමඟින්
අනේ මගේ password එක හැක් උනාද? මේ දවස්වල අපිට නිතර අහන්න ලැබෙන දෙයක්. අපි හැමෝම online ඉන්න කාලෙක, අපේ දත්තවල ආරක්ෂාව ගැන හිතන එක අත්යවශ්ය දෙයක් වෙලා. විශේෂයෙන්ම, ඔයාලා software developer කෙනෙක් නම්, user data, ඒ කියන්නේ passwords ආරක්ෂා කරන එක ඔයාලගේ ප්රධාන වගකීමක්. අද අපි කතා කරන්න යන්නේ Spring Boot application එකක passwords ආරක්ෂිතව handle කරන්නේ කොහොමද කියන එක ගැන. මේකට අපිට ලොකු උදව්වක් වෙනවා BCryptPasswordEncoder කියන කෙනා.
ඉතින්, අපි හැමෝම දන්නවා, passwords plain text විදියට database එකක ගබඩා කරන එක නිකම්ම නිකං බෝම්බයක් හංගන් ඉන්නවා වගේ වැඩක් කියලා. ඒ කියන්නේ, කවදාහරි දවසක data breach එකක් උනොත්, හැමෝගේම passwords leak වෙනවා. එතකොට අමාරුවේ වැටෙන්නේ කවුද? ඔයාගේ application එක පාවිච්චි කරන userලා. ඒ නිසා තමයි අපි හැමවිටම passwords encode කරලා හරි, hash කරලා හරි save කරන්න ඕනේ.
අද මේ article එකෙන් අපි බලමු:
- ඇයි අපි passwords encode කරන්න ඕනේ?
- BCryptPasswordEncoder කියන්නේ මොකක්ද?
- Spring Boot එකට BCryptPasswordEncoder එක එකතු කරගන්නේ කොහොමද?
- Passwords encode කරන්නේ සහ verify කරන්නේ කොහොමද?
- මේක භාවිතයේදී සැලකිලිමත් විය යුතු දේවල් මොනවාද?
හරි එහෙනම්, අපි වැඩේට බහිමු!
ඇයි අපි Passwords Encode කරන්න ඕනෙ? (Why do we need to encode Passwords?)
දැන් හිතන්නකෝ, ඔයාගේ application එකට users ලක්ෂ ගානක් ඉන්නවා කියලා. ඔයා ඒ හැමෝගෙම passwords database එකේ save කරලා තියෙන්නේ 'ABC12345' වගේ plain text විදියට. එතකොට දවසක් ඔයාගේ database එක hack උනොත් මොකද වෙන්නේ? හැකර්ට පුළුවන් හැමෝගෙම passwords එකපාරටම හොරකම් කරන්න. මේක සිරියස් කතාවක්, මොකද ගොඩක් අය හැම site එකටම එකම password එක පාවිච්චි කරනවනේ. ඒ නිසා, ඔයාගේ app එකෙන් password එකක් leak උනොත්, ඒ userගේ අනිත් accounts (email, social media, bank) පවා අන්තරායේ වැටෙනවා. මේක නිකම්ම නිකං data leak එකක් නෙමෙයි, user confidence එක සම්පූර්ණයෙන්ම නැතිවෙනවා වගේම, නීතිමය ගැටලුත් ඇතිවෙන්න පුළුවන්.
ඒ නිසා තමයි අපි passwords plain text විදියට කවදාවත් save නොකරන්නේ. ඒ වෙනුවට, අපි ඒවා 'one-way' hash functions පාවිච්චි කරලා, නැවත decrypt කරන්න බැරි විදියට encode කරනවා. ඒ කියන්නේ, original password එකෙන් encode කරපු එකක් හදන්න පුළුවන්, හැබැයි encode කරපු එකෙන් original password එක ආපහු ගන්න බෑ.
BCryptPasswordEncoder කියන්නේ මොකක්ද? (What is BCryptPasswordEncoder?)
දැන් මේ encode කරන වැඩේට ගොඩක් Algorithms තියෙනවා: MD5, SHA-1, SHA-256, SHA-512 වගේ ඒවා. හැබැයි මේවායින් ගොඩක් ඒවා දැන් old school. ඒ කියන්නේ, මේවාට විරුද්ධව 'brute-force attacks' සහ 'rainbow table attacks' කියන ඒවයින් ආරක්ෂාව අඩුයි. ඒ කියන්නේ හැකර්ට පුළුවන් ගොඩක් ඉක්මනට මේවා decode කරන්න.
මෙන්න මේකට තමයි BCrypt කියන කෙනා එන්නේ. BCrypt කියන්නේ password hashing සඳහාම හදපු, secure, adaptive, 'one-way' hash function එකක්. මේකේ විශේෂත්වය තමයි 'salt' එකක් auto generate කරන එක සහ 'cost factor' එකක් තියෙන එක.
- Salt: මේක අහඹු විදියට generate වෙන අකුරු සහ ඉලක්කම් වගේ දෙයක්. හැම password එකකටම වෙනස් salt එකක් generate වෙනවා. මේකෙන් 'rainbow table attacks' වළක්වනවා. ඒ කියන්නේ එකම password එකට වුනත් encode කලහම හැමවෙලේම වෙනස් hash එකක් තමයි එන්නේ.
- Cost Factor: මේකෙන් කියවෙන්නේ hashing process එකේදී කොච්චර 'work' එකක් කරන්න ඕනෙද කියන එක. මේක වැඩි කරන තරමට hashing එකට යන කාලය වැඩි වෙනවා. ඒ කියන්නේ brute-force attacks කරන්න යන කාලය වැඩි වෙනවා. Hardware බලය වැඩි වෙනකොට අපිට මේ cost factor එකත් වැඩි කරන්න පුළුවන්. ඒක තමයි 'adaptive' කියන්නේ.
Spring Security framework එකේ BCryptPasswordEncoder කියන class එක අපිට මේ BCrypt algorithm එක පාවිච්චි කරන්න පහසුකම් සලසනවා. මේක Spring Security වල default password encoder එක විදියටත් එනවා.
Spring Boot එකට BCryptPasswordEncoder එක එකතු කරගන්නේ කොහොමද? (How to integrate BCryptPasswordEncoder into Spring Boot?)
හරි, දැන් අපි බලමු මේ BCryptPasswordEncoder එක අපේ Spring Boot project එකට එකතු කරගන්නේ කොහොමද කියලා. මුලින්ම අපිට Spring Security dependency එක project එකට එකතු කරගන්න ඕනේ. ඔයා Maven පාවිච්චි කරනවා නම්, pom.xml එකට මේ ටික එකතු කරන්න:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
ඊළඟට, BCryptPasswordEncoder එක Spring Bean එකක් විදියට define කරන්න ඕනේ. මේක සාමාන්යයෙන් Spring Security configuration class එකක තමයි කරන්නේ. අපි පොඩි Configuration class එකක් හදමු.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@Configuration
public class SecurityConfig {
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
මෙතනදී අපි @Configuration
annotation එකෙන් මේ class එක Spring configuration class එකක් විදියට හඳුන්වලා දෙනවා. @Bean
annotation එකෙන් කියන්නේ passwordEncoder()
method එකෙන් return කරන BCryptPasswordEncoder
object එක Spring Context එකේ Bean එකක් විදියට තියාගන්න කියලා. එතකොට අපිට පුළුවන් මේ Bean එක ඕනෑම තැනක @Autowired
කරලා පාවිච්චි කරන්න.
Password Encode කිරීම සහ Verify කිරීම (Encoding and Verifying Passwords)
දැන් අපි බලමු passwords encode කරන්නේ කොහොමද සහ login වෙනකොට ඒවා verify කරන්නේ කොහොමද කියලා. මේකට අපි BCryptPasswordEncoder
එකේ තියෙන encode()
සහ matches()
කියන methods දෙක පාවිච්චි කරනවා.
Password Encode කිරීම (Encoding a Password)
User කෙනෙක් register වෙනකොට හරි, password එක change කරනකොට හරි, අපි එයා දෙන plain text password එක encode()
method එකෙන් encode කරලා තමයි database එකේ save කරන්නේ. නිකන් හිතන්නකෝ ඔයාට UserService
එකක් තියෙනවා කියලා.
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
@Service
public class UserService {
private final BCryptPasswordEncoder passwordEncoder;
// Assuming you have a UserRepository to save users
// private final UserRepository userRepository;
public UserService(BCryptPasswordEncoder passwordEncoder /*, UserRepository userRepository*/) {
this.passwordEncoder = passwordEncoder;
// this.userRepository = userRepository;
}
public User registerNewUser(String username, String rawPassword) {
String encodedPassword = passwordEncoder.encode(rawPassword);
// Now save the 'encodedPassword' to the database along with the username
// User newUser = new User(username, encodedPassword);
// return userRepository.save(newUser);
System.out.println("Encoded Password for " + username + ": " + encodedPassword);
// For demonstration, returning a dummy user
return new User(username, encodedPassword);
}
// Dummy User class for demonstration
static class User {
String username;
String password;
public User(String username, String password) {
this.username = username;
this.password = password;
}
}
}
මෙහිදී, passwordEncoder.encode(rawPassword)
කියන method එක තමයි actual encoding එක කරන්නේ. මේකෙන් අපිට ලැබෙන්නේ hash කරපු, salt එකත් එක්ක තියෙන password string එකක්.
Password Verify කිරීම (Verifying a Password)
User කෙනෙක් login වෙනකොට, එයා දෙන password එක database එකේ තියෙන encoded password එකත් එක්ක verify කරන්න ඕනේ. මේකට අපි matches()
method එක පාවිච්චි කරනවා. මේ method එකට plain text password එකයි, database එකේ තියෙන encoded password එකයි දෙකම දෙන්න ඕනේ. ඒකෙන් true/false එකක් return කරනවා.
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
@Service
public class UserService {
private final BCryptPasswordEncoder passwordEncoder;
// private final UserRepository userRepository;
public UserService(BCryptPasswordEncoder passwordEncoder /*, UserRepository userRepository*/) {
this.passwordEncoder = passwordEncoder;
// this.userRepository = userRepository;
}
public boolean authenticateUser(String username, String rawPassword) {
// Fetch the stored encoded password from your database for the given username
// String storedEncodedPassword = userRepository.findByUsername(username).getPassword();
// For demonstration purposes, let's assume a stored password (you'd fetch this from DB)
String storedEncodedPassword = "$2a$10$w4r2N5UfP2QxL8VpY0Z6.u/1x.Y.0X.0Y0Z6.u/1x.Y.0X.0Y0Z6"; // Example for 'test123'
if (storedEncodedPassword == null) {
return false; // User not found
}
boolean passwordMatches = passwordEncoder.matches(rawPassword, storedEncodedPassword);
if (passwordMatches) {
System.out.println("User " + username + " authenticated successfully.");
} else {
System.out.println("Authentication failed for user " + username + ".");
}
return passwordMatches;
}
}
මෙහිදී, passwordEncoder.matches(rawPassword, storedEncodedPassword)
කියන method එකෙන් plain text password එකයි, database එකේ තියෙන hash කරපු password එකයි දෙකම match කරනවා. මේකෙන් හැමවෙලාවෙම true
හෝ false
එකක් තමයි return කරන්නේ. අපිට direct hash එකෙන් original password එක ආපහු ගන්න බෑ කියන එක මතක තියාගන්න.
BCryptPasswordEncoder භාවිතයේදී සැලකිලිමත් විය යුතු දේවල් (Considerations when using BCryptPasswordEncoder)
- Cost Factor:
BCryptPasswordEncoder
එක initialize කරනකොට අපිට cost factor එකක් දෙන්න පුළුවන් (new BCryptPasswordEncoder(12)
වගේ). Default එක 10. මේක වැඩි කරන තරමට hashing process එකට යන කාලය වැඩි වෙනවා, ඒ වගේම security එකත් වැඩි වෙනවා. හැබැයි ඕනවට වඩා වැඩි කලොත් application එකේ performance එකට බලපාන්න පුළුවන්. ඔයාගේ server hardware එකට සරිලන විදියට මේක adjust කරගන්න එක වැදගත්. හැබැයි හැකර් කෙනෙකුට password එකක් decode කරන්න යන කාලය වැඩි වෙනවා වගේම, ඔයාගේ server එකට login එකක් authenticate කරන්න යන කාලයත් වැඩි වෙනවා. - Salt Generation: BCryptPasswordEncoder එකෙන් salt එක auto generate කරන නිසා ඒ ගැන බය වෙන්න දෙයක් නෑ. ඒක හැමවෙලේම secure salt එකක් තමයි use කරන්නේ.
- Raw Password Storage: කවදාවත් plain text password එකක් database එකේ save කරන්න එපා. Encoded password එක විතරක් save කරන්න.
- Dependencies Update: හැමවෙලාවෙම Spring Security සහ අනෙකුත් dependencies latest stable versions වල තියාගන්න. Security fixes නිතරම එන නිසා ඒක වැදගත්.
අවසන් වශයෙන් (Finally)
ඉතින් යාලුවනේ, ඔයාලා දැක්කා නේද BCryptPasswordEncoder එක පාවිච්චි කරලා Spring Boot application එකක passwords කොච්චර ආරක්ෂිතව handle කරන්න පුළුවන්ද කියලා. මේක අනිවාර්යයෙන්ම ඔයාලගේ project වලට එකතු කරගන්න ඕන feature එකක්. User data security කියන්නේ developer කෙනෙක් විදියට අපේ වගකීමක්. පොඩි දෙයක් වගේ පෙනුනත් මේකෙන් ලොකු හානියක් වළක්වා ගන්න පුළුවන්.
මතක තියාගන්න, security කියන්නේ එක වරක් කරන දෙයක් නෙමෙයි, නිතරම අවධානයෙන් ඉන්න ඕන දෙයක්. මේ ගැන ඔයාලගේ අදහස්, ප්රශ්න පහලින් comment කරන්න. මේ වගේ තව articles ඕනේද කියලත් කියන්න.
ජය වේවා!