Spring Security এবং JWT (JSON Web Token) একসঙ্গে ব্যবহৃত হলে একটি শক্তিশালী অথেনটিকেশন এবং অথরাইজেশন সিস্টেম তৈরি করা যায়। JWT সাধারণত stateless authentication এর জন্য ব্যবহৃত হয়, যেখানে সার্ভার কোনও স্টেট (যেমন, সেশন) ট্র্যাক করে না। এই কারণে, JWT একটি RESTful API বা মাইক্রোসার্ভিস অ্যাপ্লিকেশন তৈরির জন্য আদর্শ।
JWT ব্যবহার করার মাধ্যমে, আপনি একটি টোকেন তৈরি করতে পারেন যা ব্যবহারকারীর তথ্য (যেমন: ব্যবহারকারীর নাম, রোল, ইত্যাদি) ধারণ করে এবং এটি সার্ভারকে জানাতে সক্ষম হয় যে ব্যবহারকারী বৈধ।
Spring Security ব্যবহার করে JWT টোকেন বেসড অথেনটিকেশন সেটআপ করার জন্য নিচে প্রক্রিয়া দেওয়া হল।
প্রথমে, আপনার pom.xml
ফাইলে Spring Security এবং JWT লাইব্রেরি যুক্ত করুন:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
</dependencies>
JWT টোকেন তৈরি এবং যাচাই করার জন্য একটি Utility ক্লাস তৈরি করুন:
package com.example.security;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
public class JwtUtil {
private final String SECRET_KEY = "mySecretKey"; // Secret key for signing the JWT
// Generate JWT Token
public String generateToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10)) // Valid for 10 hours
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
// Extract username from token
public String extractUsername(String token) {
return extractClaims(token).getSubject();
}
// Extract claims (like expiration date, etc.)
public Claims extractClaims(String token) {
return Jwts.parser()
.setSigningKey(SECRET_KEY)
.parseClaimsJws(token)
.getBody();
}
// Check if token is expired
private boolean isTokenExpired(String token) {
return extractClaims(token).getExpiration().before(new Date());
}
// Validate the token
public boolean validateToken(String token, String username) {
return (username.equals(extractUsername(token)) && !isTokenExpired(token));
}
}
JWT টোকেন যাচাই করার জন্য একটি filter তৈরি করুন:
package com.example.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class JwtRequestFilter extends OncePerRequestFilter {
@Autowired
private JwtUtil jwtUtil;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws javax.servlet.ServletException, java.io.IOException {
final String authorizationHeader = request.getHeader("Authorization");
String username = null;
String jwt = null;
if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
jwt = authorizationHeader.substring(7); // Get the token from "Bearer <token>"
username = jwtUtil.extractUsername(jwt);
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
if (jwtUtil.validateToken(jwt, username)) {
UsernamePasswordAuthenticationToken authenticationToken =
new UsernamePasswordAuthenticationToken(username, null, new ArrayList<>());
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
}
}
chain.doFilter(request, response);
}
}
Spring Security কনফিগারেশন ক্লাস তৈরি করুন যেখানে JWT Request Filter এবং অন্যান্য নিরাপত্তা কনফিগারেশন থাকবে:
package com.example.security;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JwtRequestFilter jwtRequestFilter;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable() // Disable CSRF for simplicity
.authorizeRequests()
.antMatchers("/authenticate").permitAll() // Permit authenticate endpoint for everyone
.anyRequest().authenticated() // All other requests need authentication
.and()
.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class); // Add JWT filter before the standard UsernamePasswordAuthenticationFilter
}
}
এখন একটি কন্ট্রোলার তৈরি করুন যেখানে ব্যবহারকারী JWT টোকেন পাবেন:
package com.example.controller;
import com.example.security.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
public class AuthenticationController {
@Autowired
private JwtUtil jwtUtil;
@PostMapping("/authenticate")
public String createToken(@RequestParam String username) {
// In a real-world scenario, authenticate the user with username and password
return jwtUtil.generateToken(username); // Generate JWT token
}
}
/authenticate
এ ব্যবহারকারীর নাম পাঠিয়ে একটি JWT টোকেন পেতে হবে।Authorization
হেডারে "Bearer " সহ সার্ভারে পাঠাতে হবে।Example Request:
POST /authenticate?username=johnDoe HTTP/1.1
Host: localhost:8080
Example Response:
{
"token": "<JWT_TOKEN>"
}
এবং পরবর্তী রিকোয়েস্টে JWT টোকেন পাঠান:
GET /secure-endpoint HTTP/1.1
Host: localhost:8080
Authorization: Bearer <JWT_TOKEN>
Spring Security এবং JWT ব্যবহার করে আপনি একটি নিরাপদ এবং স্ট্যাটলেস অথেনটিকেশন সিস্টেম তৈরি করতে পারেন। JWT বেসড অথেনটিকেশন RESTful অ্যাপ্লিকেশন এবং মাইক্রোসার্ভিস আর্কিটেকচারে খুবই জনপ্রিয়, কারণ এটি সেশন ট্র্যাকিং ছাড়াই ব্যবহারকারীর পরিচয় যাচাই করতে সহায়ক।
JSON Web Token (JWT) একটি কমপ্যাক্ট এবং সুরক্ষিত টোকেন ফরম্যাট যা JSON-ভিত্তিক ডেটা এনকোড করে একটি সাইনড স্ট্রিং আকারে আদান-প্রদান করা হয়। এটি সাধারণত অ্যাপ্লিকেশনগুলোর Authentication এবং Authorization এর জন্য ব্যবহৃত হয়।
JWT প্রধানত নিম্নলিখিত কারণগুলোতে ব্যবহৃত হয়:
JWT তিনটি অংশে বিভক্ত থাকে এবং প্রতিটি অংশ ডট (.
) দিয়ে পৃথক করা হয়:
HEADER.PAYLOAD.SIGNATURE
উদাহরণ:
{
"alg": "HS256",
"typ": "JWT"
}
উদাহরণ:
{
"sub": "1234567890",
"name": "John Doe",
"role": "ADMIN",
"exp": 1688000000
}
উদাহরণ:
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secretKey
)
ক্লায়েন্ট পরবর্তী API রিকোয়েস্টের সাথে Authorization
হেডারে JWT পাঠায়:
Authorization: Bearer <JWT_TOKEN>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
public class JwtUtil {
private static final String SECRET_KEY = "secretKey";
public static String generateToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60)) // 1 hour validity
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
public static boolean validateToken(String token, String username) {
String extractedUsername = Jwts.parser()
.setSigningKey(SECRET_KEY)
.parseClaimsJws(token)
.getBody()
.getSubject();
return extractedUsername.equals(username) && !isTokenExpired(token);
}
private static boolean isTokenExpired(String token) {
Date expiration = Jwts.parser()
.setSigningKey(SECRET_KEY)
.parseClaimsJws(token)
.getBody()
.getExpiration();
return expiration.before(new Date());
}
}
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class JwtFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String authorizationHeader = request.getHeader("Authorization");
if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
String token = authorizationHeader.substring(7);
String username = JwtUtil.extractUsername(token);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
if (JwtUtil.validateToken(token, username)) {
Authentication auth = JwtUtil.getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(auth);
}
}
}
filterChain.doFilter(request, response);
}
}
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/auth/**").permitAll()
.anyRequest().authenticated()
.and()
.addFilter(new JwtFilter());
}
}
JWT একটি লাইটওয়েট এবং কার্যকর সল্যুশন যা অ্যাপ্লিকেশনগুলিতে Stateless Authentication নিশ্চিত করে। এটি বিশেষত মাইক্রোসার্ভিস এবং মোবাইল অ্যাপ্লিকেশনের মতো ডিস্ট্রিবিউটেড সিস্টেমের জন্য উপযুক্ত। Spring Security-তে JWT সহজেই ইমপ্লিমেন্ট করা যায়, যা Authentication এবং Authorization এর জন্য একটি আধুনিক এবং নিরাপদ সমাধান প্রদান করে।
JWT (JSON Web Token) একটি স্ট্যান্ডার্ড টোকেন-ভিত্তিক অথেনটিকেশন মেকানিজম। এটি সাধারণত Stateless Authentication এর জন্য ব্যবহৃত হয়। Spring Security-তে JWT Authentication কনফিগার করলে, সেশন ব্যবস্থাপনা ছাড়াই ব্যবহারকারীর তথ্য যাচাই করা যায়।
Maven Dependency:
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
JWT Token জেনারেট এবং যাচাই করার জন্য একটি Utility Class:
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import java.security.Key;
import java.util.Date;
import org.springframework.stereotype.Component;
@Component
public class JwtUtil {
private final String SECRET_KEY = "your-256-bit-secret-key"; // 256-bit Key
private final int EXPIRATION_TIME = 1000 * 60 * 60 * 10; // 10 Hours
private Key getSigningKey() {
return Keys.hmacShaKeyFor(SECRET_KEY.getBytes());
}
public String generateToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.signWith(getSigningKey(), SignatureAlgorithm.HS256)
.compact();
}
public String extractUsername(String token) {
return Jwts.parserBuilder()
.setSigningKey(getSigningKey())
.build()
.parseClaimsJws(token)
.getBody()
.getSubject();
}
public boolean isTokenValid(String token, String username) {
return username.equals(extractUsername(token)) && !isTokenExpired(token);
}
private boolean isTokenExpired(String token) {
return Jwts.parserBuilder()
.setSigningKey(getSigningKey())
.build()
.parseClaimsJws(token)
.getBody()
.getExpiration()
.before(new Date());
}
}
JWT Token যাচাই করার জন্য একটি Filter তৈরি:
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Autowired
private JwtUtil jwtUtil;
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
final String authHeader = request.getHeader("Authorization");
String username = null;
String token = null;
if (authHeader != null && authHeader.startsWith("Bearer ")) {
token = authHeader.substring(7);
username = jwtUtil.extractUsername(token);
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
if (jwtUtil.isTokenValid(token, userDetails.getUsername())) {
UsernamePasswordAuthenticationToken authToken =
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authToken);
}
}
filterChain.doFilter(request, response);
}
}
JWT Authentication যুক্ত করার জন্য Spring Security কনফিগার করা:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http, JwtAuthenticationFilter jwtAuthenticationFilter) throws Exception {
http
.csrf().disable()
.authorizeHttpRequests(auth -> auth
.requestMatchers("/login", "/register").permitAll()
.anyRequest().authenticated()
)
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception {
return configuration.getAuthenticationManager();
}
}
লগইন রিকোয়েস্ট থেকে JWT Token জেনারেট করা:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.web.bind.annotation.*;
@RestController
public class AuthController {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private JwtUtil jwtUtil;
@PostMapping("/login")
public String login(@RequestBody AuthRequest authRequest) {
try {
Authentication auth = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(authRequest.getUsername(), authRequest.getPassword()));
return jwtUtil.generateToken(authRequest.getUsername());
} catch (AuthenticationException e) {
throw new RuntimeException("Invalid username or password");
}
}
}
class AuthRequest {
private String username;
private String password;
// Getters and Setters
}
Spring Security-তে JWT Authentication কনফিগার করা একটি শক্তিশালী অথেনটিকেশন প্রক্রিয়া যা Stateless Application-এ ব্যবহৃত হয়।
এই কনফিগারেশন অ্যাপ্লিকেশনের নিরাপত্তা নিশ্চিত করে এবং Traditional Session-Based Authentication এর চেয়ে আরও স্কেলেবল।
Token ভিত্তিক Authentication, বিশেষত JWT (JSON Web Token) ব্যবহার, Spring Security এর মাধ্যমে নিরাপদ এবং কার্যকর অ্যাপ্লিকেশন তৈরি করতে সহায়ক।
Token ব্যবস্থাপনার মূল তিনটি ধাপ হলো:
Token তৈরি করার জন্য সাধারণত JWT ব্যবহার করা হয়। এটি একটি কমপ্যাক্ট এবং স্বাক্ষরযুক্ত স্ট্রিং যা ব্যবহারকারীর তথ্য বহন করে।
JWT তিনটি অংশ নিয়ে গঠিত:
username
, roles
, এবং অন্যান্য ক্লেইম।import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
public class JwtUtil {
private static final String SECRET_KEY = "mySecretKey";
private static final long EXPIRATION_TIME = 86400000; // 1 দিন
public static String generateToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
}
Token যাচাই করার সময় নিশ্চিত করতে হবে:
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureException;
public class JwtUtil {
private static final String SECRET_KEY = "mySecretKey";
public static Claims validateToken(String token) {
try {
return Jwts.parser()
.setSigningKey(SECRET_KEY)
.parseClaimsJws(token)
.getBody();
} catch (SignatureException e) {
throw new RuntimeException("Invalid JWT Signature");
} catch (Exception e) {
throw new RuntimeException("Invalid Token");
}
}
}
String token = "Bearer eyJhbGciOiJIUzI1NiIsInR...";
Claims claims = JwtUtil.validateToken(token.substring(7));
String username = claims.getSubject();
Token এর মেয়াদ নির্ধারণ করা নিরাপত্তার একটি গুরুত্বপূর্ণ অংশ। মেয়াদোত্তীর্ণ টোকেন গ্রহণ করা হলে এটি নিরাপত্তা ঝুঁকি তৈরি করতে পারে।
Token তৈরি করার সময় setExpiration
ফিল্ড ব্যবহার করে মেয়াদ নির্ধারণ করা হয়।
private static final long EXPIRATION_TIME = 3600000; // 1 ঘন্টা
Spring Security স্বয়ংক্রিয়ভাবে মেয়াদোত্তীর্ণ টোকেনের জন্য একটি ExpiredJwtException
ছুঁড়ে দেয়। এটি যাচাই করার জন্য:
public static boolean isTokenExpired(String token) {
Claims claims = validateToken(token);
return claims.getExpiration().before(new Date());
}
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String token = request.getHeader("Authorization");
if (token != null && token.startsWith("Bearer ")) {
token = token.substring(7);
if (!JwtUtil.isTokenExpired(token)) {
Claims claims = JwtUtil.validateToken(token);
String username = claims.getSubject();
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
username, null, new ArrayList<>());
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
filterChain.doFilter(request, response);
}
}
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/login", "/register").permitAll()
.anyRequest().authenticated()
.and()
.addFilter(new JwtAuthenticationFilter());
}
}
/refresh
এন্ডপয়েন্ট ব্যবহার করা যায়।Header
, Payload
, এবং Signature
সঠিকভাবে সংজ্ঞায়িত করুন।Spring Security এর মাধ্যমে Token Based Authentication সহজেই সুরক্ষিত এবং স্কেলেবল অ্যাপ্লিকেশন তৈরি করা যায়।
JWT (JSON Web Token) হল একটি স্ট্যান্ডার্ড টোকেন-ভিত্তিক প্রমাণীকরণ এবং অনুমোদনের পদ্ধতি, যেখানে একটি কমপ্যাক্ট এবং সেলফ-কনটেইনড টোকেন ব্যবহার করা হয়। Spring Security-তে JWT Authentication এবং Authorization কনফিগার করার জন্য নিচে একটি স্টেপ-বাই-স্টেপ উদাহরণ দেওয়া হলো।
Spring Boot এবং JWT লাইব্রেরি যুক্ত করতে pom.xml
বা build.gradle
-এ ডিপেন্ডেন্সি যোগ করুন।
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'io.jsonwebtoken:jjwt:0.9.1'
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
public class JwtUtil {
private String secretKey = "mySecretKey";
private long expirationTime = 1000 * 60 * 60; // 1 hour
// টোকেন তৈরি
public String generateToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + expirationTime))
.signWith(SignatureAlgorithm.HS256, secretKey)
.compact();
}
// টোকেন থেকে ইউজারনেম বের করা
public String extractUsername(String token) {
return getClaims(token).getSubject();
}
// টোকেন এক্সপায়ার্ড কিনা যাচাই
public boolean isTokenExpired(String token) {
return getClaims(token).getExpiration().before(new Date());
}
// টোকেন যাচাই
public boolean validateToken(String token, String username) {
return (username.equals(extractUsername(token)) && !isTokenExpired(token));
}
// প্রাইভেট মেথড: Claims বের করা
private Claims getClaims(String token) {
return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody();
}
}
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/authenticate", "/register").permitAll() // Public endpoints
.anyRequest().authenticated(); // Others require authentication
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user").password(passwordEncoder().encode("password")).roles("USER")
.and()
.withUser("admin").password(passwordEncoder().encode("admin")).roles("ADMIN");
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/authenticate")
public class AuthController {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private JwtUtil jwtUtil;
@PostMapping
public String generateToken(@RequestBody AuthRequest authRequest) {
try {
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(authRequest.getUsername(), authRequest.getPassword())
);
return jwtUtil.generateToken(authRequest.getUsername());
} catch (Exception e) {
throw new RuntimeException("Invalid username/password");
}
}
}
// DTO for authentication request
class AuthRequest {
private String username;
private String password;
// Getters and Setters
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class JwtFilter extends OncePerRequestFilter {
@Autowired
private JwtUtil jwtUtil;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) {
String authorizationHeader = request.getHeader("Authorization");
String token = null;
String username = null;
if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
token = authorizationHeader.substring(7);
username = jwtUtil.extractUsername(token);
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
if (jwtUtil.validateToken(token, username)) {
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
username, null, new ArrayList<>());
authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authToken);
}
}
chain.doFilter(request, response);
}
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JwtFilter jwtFilter;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/authenticate").permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
}
}
@GetMapping("/public")
public String publicEndpoint() {
return "This is a public endpoint";
}
@GetMapping("/secured")
public String securedEndpoint() {
return "This is a secured endpoint";
}
/authenticate
এ POST
রিকোয়েস্ট পাঠিয়ে টোকেন জেনারেট করুন।Bearer <token>
আকারে পাঠান।Spring Security-তে JWT Authentication এবং Authorization ইমপ্লিমেন্ট করলে আপনার অ্যাপ্লিকেশন stateless এবং নিরাপদ হয়। উপরোক্ত উদাহরণটি ব্যবহার করে আপনি সহজেই একটি JWT-ভিত্তিক Authentication সিস্টেম তৈরি করতে পারবেন।
Read more