JWT (JSON Web Token) এবং Refresh Token ইমপ্লিমেন্টেশন ব্যবহার করে আপনি স্প্রিং সিকিউরিটিতে টোকেন ভিত্তিক অথেনটিকেশন এবং অথরাইজেশন প্রক্রিয়া সেটআপ করতে পারেন। JWT টোকেন সাধারণত সেশনবিহীন অথেনটিকেশন সরবরাহ করে, যা একটি শক্তিশালী নিরাপত্তা বৈশিষ্ট্য হিসেবে কাজ করে। Refresh Token ব্যবহার করলে, ব্যবহারকারী লগ ইন থাকার সময় তার অ্যাক্সেস টোকেনটি পুনর্নবীকরণ করতে পারে, এবং এটি সময়সীমার মধ্যে নতুন অ্যাক্সেস টোকেন পেতে সহায়ক।
এখানে Spring Security এবং JWT Refresh Token ইমপ্লিমেন্টেশন একটি উদাহরণের মাধ্যমে ব্যাখ্যা করা হয়েছে।
pom.xml ফাইলে নিম্নলিখিত ডিপেন্ডেন্সি যোগ করুন:
<dependencies>
<!-- Spring Boot Web Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Boot Security Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- Spring Boot Starter OAuth2 Client -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<!-- JWT Library -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.11.5</version>
</dependency>
<!-- Spring Boot Starter Data JPA (for user management if needed) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
</dependencies>
JWT টোকেন তৈরি এবং যাচাই করার জন্য একটি JwtTokenUtil
ক্লাস তৈরি করুন:
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
public class JwtTokenUtil {
private String secretKey = "yourSecretKey"; // Secret key for signing JWT
private long accessTokenValidity = 1000 * 60 * 60; // 1 hour for access token
private long refreshTokenValidity = 1000 * 60 * 60 * 24 * 7; // 1 week for refresh token
// Create Access Token
public String generateAccessToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + accessTokenValidity))
.signWith(SignatureAlgorithm.HS512, secretKey)
.compact();
}
// Create Refresh Token
public String generateRefreshToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + refreshTokenValidity))
.signWith(SignatureAlgorithm.HS512, secretKey)
.compact();
}
// Parse Claims
public Claims getClaims(String token) {
return Jwts.parser()
.setSigningKey(secretKey)
.parseClaimsJws(token)
.getBody();
}
// Validate Token
public boolean isTokenExpired(String token) {
return getClaims(token).getExpiration().before(new Date());
}
// Get Username from Token
public String getUsernameFromToken(String token) {
return getClaims(token).getSubject();
}
// Validate Access Token
public boolean validateAccessToken(String token, String username) {
return (username.equals(getUsernameFromToken(token)) && !isTokenExpired(token));
}
}
স্প্রিং সিকিউরিটিতে JWT অথেনটিকেশন এবং রিফ্রেশ টোকেন ব্যবহারের জন্য SecurityConfig
কনফিগারেশন ক্লাস তৈরি করুন।
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;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final JwtTokenUtil jwtTokenUtil;
public SecurityConfig(JwtTokenUtil jwtTokenUtil) {
this.jwtTokenUtil = jwtTokenUtil;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/auth/**").permitAll() // Allow public access to auth routes
.anyRequest().authenticated() // Require authentication for other routes
.and()
.addFilter(new JwtAuthenticationFilter(authenticationManager(), jwtTokenUtil));
}
}
JWT টোকেন যাচাই এবং অনুমোদন পরিচালনা করার জন্য একটি ফিল্টার তৈরি করুন।
import io.jsonwebtoken.ExpiredJwtException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
public class JwtAuthenticationFilter extends OncePerRequestFilter {
private final JwtTokenUtil jwtTokenUtil;
public JwtAuthenticationFilter(JwtTokenUtil jwtTokenUtil) {
this.jwtTokenUtil = jwtTokenUtil;
}
@Override
protected void doFilterInternal(HttpServletRequest request, javax.servlet.FilterChain chain) throws ServletException, IOException {
String token = getJwtFromRequest(request);
if (token != null && jwtTokenUtil.validateAccessToken(token, getUsernameFromToken(token))) {
// Set authentication context
SecurityContextHolder.getContext().setAuthentication(new JwtAuthenticationToken(getUsernameFromToken(token)));
}
chain.doFilter(request, response);
}
// Extract JWT from the request header
private String getJwtFromRequest(HttpServletRequest request) {
String bearerToken = request.getHeader("Authorization");
if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring(7);
}
return null;
}
// Get Username from Token
private String getUsernameFromToken(String token) {
return jwtTokenUtil.getUsernameFromToken(token);
}
}
এখন আপনি AuthenticationController তৈরি করতে পারেন যা Login, Generate Access Token, এবং Refresh Token প্রদান করবে।
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/auth")
public class AuthenticationController {
private final JwtTokenUtil jwtTokenUtil;
@Autowired
public AuthenticationController(JwtTokenUtil jwtTokenUtil) {
this.jwtTokenUtil = jwtTokenUtil;
}
// Generate Access Token and Refresh Token
@PostMapping("/login")
public JwtResponse login(@RequestBody LoginRequest loginRequest) {
// Normally you'd authenticate the user here
String username = loginRequest.getUsername(); // Assume user is authenticated
String accessToken = jwtTokenUtil.generateAccessToken(username);
String refreshToken = jwtTokenUtil.generateRefreshToken(username);
return new JwtResponse(accessToken, refreshToken);
}
// Refresh Token
@PostMapping("/refresh")
public JwtResponse refresh(@RequestBody RefreshRequest refreshRequest) {
String refreshToken = refreshRequest.getRefreshToken();
String username = jwtTokenUtil.getUsernameFromToken(refreshToken);
// Optionally validate refresh token here
String newAccessToken = jwtTokenUtil.generateAccessToken(username);
return new JwtResponse(newAccessToken, refreshToken);
}
}
public class LoginRequest {
private String username;
private String password;
// Getters and Setters
}
public class RefreshRequest {
private String refreshToken;
// Getter and Setter
}
public class JwtResponse {
private String accessToken;
private String refreshToken;
public JwtResponse(String accessToken, String refreshToken) {
this.accessToken = accessToken;
this.refreshToken = refreshToken;
}
// Getters and Setters
}
এই উদাহরণটি Spring Security এবং JWT Refresh Token ইমপ্লিমেন্টেশন কভার করে, যা Access Token এবং Refresh Token প্রক্রিয়া পরিচালনা করে। ব্যবহারকারী লগইন করলে একটি Access Token এবং একটি Refresh Token প্রদান করা হয়, এবং যখন Access Token এর মেয়াদ শেষ হয়ে যায়, তখন Refresh Token এর মাধ্যমে নতুন Access Token পাওয়া যায়।
এটি stateless authentication এ সহায়ক এবং অ্যাপ্লিকেশনগুলিতে নিরাপত্তা প্রদান করে।
Refresh Token একটি নিরাপদ টোকেন যা Access Token পুনঃপ্রাপ্ত করার জন্য ব্যবহৃত হয়। সাধারণত, Access Token (যা JWT-এ থাকে) একটি নির্দিষ্ট সময় (যেমন, ১ ঘণ্টা) পর্যন্ত বৈধ থাকে এবং পরবর্তী সময়ে এটি expire হয়ে যায়। কিন্তু ব্যবহারকারীকে বারবার লগইন করার পরিবর্তে Refresh Token ব্যবহার করে নতুন Access Token জেনারেট করা যায়।
একটি Refresh Token দীর্ঘ সময়ের জন্য বৈধ থাকে, তবে Access Token-এর মতো এটি সাধারণত ক্লায়েন্ট-সার্ভারে স্টোর করা হয় না। Refresh Token শুধুমাত্র সেই সময়ে ব্যবহার করা হয় যখন Access Token মেয়াদ উত্তীর্ণ হয়ে যায়।
Spring Security-তে JWT ভিত্তিক Refresh Token ইমপ্লিমেন্ট করার জন্য সাধারণত নিচের স্টেপগুলো অনুসরণ করা হয়:
JWT Utility ক্লাসে Access Token এবং Refresh Token তৈরি ও যাচাই করার জন্য মেথড তৈরি করুন:
public class JwtUtil {
private final String SECRET_KEY = "mySecretKey";
public String generateAccessToken(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 String generateRefreshToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 7)) // 7 days validity
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
public boolean validateToken(String token, String username) {
String extractedUsername = extractUsername(token);
return (username.equals(extractedUsername) && !isTokenExpired(token));
}
private String extractUsername(String token) {
return extractClaims(token).getSubject();
}
private Claims extractClaims(String token) {
return Jwts.parser()
.setSigningKey(SECRET_KEY)
.parseClaimsJws(token)
.getBody();
}
private boolean isTokenExpired(String token) {
return extractClaims(token).getExpiration().before(new Date());
}
}
একটি কন্ট্রোলার তৈরি করুন যেখানে ব্যবহারকারী তাদের Refresh Token প্রদান করবে এবং নতুন Access Token প্রাপ্ত করবে।
@RestController
public class TokenController {
@Autowired
private JwtUtil jwtUtil;
@PostMapping("/refresh-token")
public ResponseEntity<?> refreshToken(@RequestParam String refreshToken) {
String username = jwtUtil.extractUsername(refreshToken);
// Validate Refresh Token (You can check for validity and expiration)
if (username != null && jwtUtil.validateToken(refreshToken, username)) {
String newAccessToken = jwtUtil.generateAccessToken(username);
return ResponseEntity.ok(newAccessToken);
} else {
return ResponseEntity.status(HttpStatus.FORBIDDEN).body("Invalid Refresh Token");
}
}
}
Refresh Token ব্যবহারকারীর অভিজ্ঞতাকে আরো উন্নত করে এবং দীর্ঘ সময়ের জন্য নিরাপদ অথেনটিকেশন প্রদান করতে সাহায্য করে। এটি JWT এর সাথে যুক্ত করে অ্যাপ্লিকেশনের নিরাপত্তা এবং ব্যবহারকারীর অভিজ্ঞতাকে শক্তিশালী করে।
JWT Authentication ব্যবহারের সময়, সাধারণত Access Token এর মেয়াদ শেষ হয়ে গেলে নতুন Access Token প্রাপ্ত করার জন্য একটি Refresh Token ব্যবহার করা হয়। Refresh Token দিয়ে একটি নতুন Access Token তৈরি করা যায়, যাতে ব্যবহারকারীর পুনরায় লগইন করার প্রয়োজন না হয়। এই প্রক্রিয়াটি Stateless Authentication এর সুবিধা বজায় রেখে নিরাপদে সেশন পরিচালনা করতে সাহায্য করে।
নিম্নে, Spring Security তে JWT Refresh Token কনফিগার করার জন্য ধাপে ধাপে নির্দেশনা দেওয়া হলো।
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.Claims;
import java.util.Date;
public class JwtUtil {
private static final String SECRET_KEY = "secretKey"; // নিরাপদ রাখতে এই কীটি ভালোভাবে কনফিগার করতে হবে
// Access Token জেনারেট করা
public static String generateAccessToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 15)) // 15 মিনিট
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
// Refresh Token জেনারেট করা
public static String generateRefreshToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 24)) // 24 ঘন্টা
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
// টোকেনের মধ্যে তথ্য বের করা
public static Claims extractClaims(String token) {
return Jwts.parser()
.setSigningKey(SECRET_KEY)
.parseClaimsJws(token)
.getBody();
}
// টোকেনের ভ্যালিডিটি চেক করা
public static boolean isTokenExpired(String token) {
Date expiration = extractClaims(token).getExpiration();
return expiration.before(new Date());
}
// টোকেন থেকে ইউজার নাম বের করা
public static String extractUsername(String token) {
return extractClaims(token).getSubject();
}
// টোকেন ভ্যালিডেশন
public static boolean validateToken(String token, String username) {
return (username.equals(extractUsername(token)) && !isTokenExpired(token));
}
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/auth")
public class AuthController {
@Autowired
private JwtUtil jwtUtil;
@PostMapping("/login")
public String login(@RequestParam String username, @RequestParam String password) {
// এখানে ইউজারনেম এবং পাসওয়ার্ড চেক করতে হবে (ধরি, সফল লগইন)
String accessToken = jwtUtil.generateAccessToken(username);
String refreshToken = jwtUtil.generateRefreshToken(username);
// ইউজারের জন্য access token এবং refresh token রিটার্ন করা
return "Access Token: " + accessToken + "\nRefresh Token: " + refreshToken;
}
@PostMapping("/refresh")
public String refreshToken(@RequestParam String refreshToken) {
if (jwtUtil.isTokenExpired(refreshToken)) {
return "Refresh Token expired!";
}
String username = jwtUtil.extractUsername(refreshToken);
String newAccessToken = jwtUtil.generateAccessToken(username);
return "New Access Token: " + newAccessToken;
}
}
/login
রিকোয়েস্টে ইউজারনেম এবং পাসওয়ার্ড দিয়ে সফল লগইন হলে, Access Token এবং Refresh Token তৈরি হবে।/refresh
রিকোয়েস্টে Refresh Token পাঠালে, যদি Refresh Token বৈধ থাকে, তবে নতুন Access Token জেনারেট হবে।Spring Security কনফিগারেশন তৈরি করতে হবে যাতে /login
এবং /refresh
এ অননুমোদিত অ্যাক্সেস বন্ধ করা যায়।
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;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/auth/login", "/auth/refresh").permitAll() // Login এবং Refresh API কে খোলা রাখা
.anyRequest().authenticated() // অন্য সব রিকোয়েস্টের জন্য Authentication প্রয়োজন
.and()
.formLogin().disable(); // ডিফল্ট লগইন ফর্ম নিষ্ক্রিয় করা
}
}
আপনি যদি JWT ব্যবহার করে API গুলোতে সিকিউরিটি পরিচালনা করতে চান, তবে একটি JWT Filter যুক্ত করতে পারেন। এটি নিশ্চিত করবে যে প্রতিটি API রিকোয়েস্টে Authorization
হেডারে JWT পাঠানো হচ্ছে এবং সেটি ভ্যালিড কিনা চেক করবে।
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)) {
// Add authentication object to context
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(username, null, new ArrayList<>()));
}
}
}
filterChain.doFilter(request, response);
}
}
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<JwtFilter> jwtFilter() {
FilterRegistrationBean<JwtFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new JwtFilter());
registrationBean.addUrlPatterns("/api/*"); // সমস্ত API রিকোয়েস্টে ফিল্টার কার্যকর হবে
return registrationBean;
}
}
POST http://localhost:8080/auth/login?username=user&password=pass
POST http://localhost:8080/auth/refresh?refreshToken=<Refresh_Token>
Spring Security তে JWT Refresh Token কনফিগার করা একটি কার্যকরী সমাধান যেটি ব্যবহারকারীর সেশন ম্যানেজমেন্ট এবং অ্যাপ্লিকেশনের নিরাপত্তা উন্নত করতে সাহায্য করে। Access Token এর মেয়াদ শেষ হয়ে গেলে Refresh Token এর মাধ্যমে সহজেই নতুন Access Token তৈরি করা যায়, যাতে ব্যবহারকারীকে পুনরায় লগইন করতে না হয়।
JWT (JSON Web Token) Authentication ব্যবহারের সময়, Token Expiration এবং Refresh Token তৈরি করা গুরুত্বপূর্ণ বিষয় হয়ে দাঁড়ায়। JWT-তে একটি নির্দিষ্ট সময়সীমা থাকে, যার পর টোকেনটির বৈধতা শেষ হয়ে যায় (Expiration)। তখন ব্যবহারকারীকে পুনরায় লগইন করতে হতে পারে বা Refresh Token ব্যবহার করে নতুন টোকেন পাওয়া যায়। এই প্রক্রিয়াগুলি Spring Security-তে কিভাবে কনফিগার করতে হয় তা আলোচনা করা হবে।
JWT-এর expiration
ফিল্ড ব্যবহারকারীকে একটি টোকেনের বৈধতার সময়সীমা নির্ধারণ করতে সাহায্য করে। যখন টোকেনটির সময়সীমা শেষ হয়, তখন এটি আর বৈধ থাকে না এবং ব্যবহারকারীকে পুনরায় অথেনটিকেট হতে হয়।
JWT Token তৈরি করার সময়, আপনি exp
(expiration) প্যারামিটার ব্যবহার করতে পারেন। এই প্যারামিটারটি সাধারণত একটি সময় (epoch time) প্রকাশ করে, যার পরে টোকেনটি মেয়াদ উত্তীর্ণ হয়ে যাবে।
উদাহরণ:
import io.jsonwebtoken.*;
import java.util.Date;
public class JwtUtil {
private final String SECRET_KEY = "your-256-bit-secret-key";
private final long EXPIRATION_TIME = 1000 * 60 * 60 * 10; // 10 hours
public String generateToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) // Set expiration
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
public boolean isTokenExpired(String token) {
return getExpirationDateFromToken(token).before(new Date());
}
public Date getExpirationDateFromToken(String token) {
return Jwts.parserBuilder()
.setSigningKey(SECRET_KEY)
.build()
.parseClaimsJws(token)
.getBody()
.getExpiration();
}
}
setExpiration
: Token এর Expiration Time নির্ধারণ করে।isTokenExpired
: Token মেয়াদ শেষ হয়েছে কিনা চেক করার জন্য ব্যবহৃত হয়।JWT এর Expiration যাচাই করার জন্য, আপনি isTokenExpired
ফাংশন ব্যবহার করতে পারেন। যদি Expiration এর পরে রিকোয়েস্ট আসে, তবে টোকেন অবৈধ হিসেবে গণ্য হবে এবং পুনরায় লগইন করতে হবে।
JWT-র Access Token
সাধারণত ছোট সময়ের জন্য মেয়াদী থাকে। যদি ব্যবহারকারী লগইন করার পর টোকেনটি মেয়াদোত্তীর্ণ হয়ে যায়, তাহলে Refresh Token ব্যবহার করে নতুন একটি Access Token তৈরি করা যেতে পারে। Refresh Token দীর্ঘমেয়াদী এবং এর মাধ্যমে নতুন Access Token জেনারেট করা যায়।
Refresh Token তৈরি করার জন্য আপনাকে একটি নতুন টোকেন তৈরির পদ্ধতি তৈরি করতে হবে, যেটি দীর্ঘমেয়াদী এবং এটি Token Expiration পর পুনরায় একটি নতুন Access Token ইস্যু করবে।
import io.jsonwebtoken.*;
import java.util.Date;
public class JwtUtil {
private final String SECRET_KEY = "your-256-bit-secret-key";
private final long ACCESS_TOKEN_EXPIRATION = 1000 * 60 * 15; // 15 minutes
private final long REFRESH_TOKEN_EXPIRATION = 1000 * 60 * 60 * 24 * 7; // 7 days
// Generate Access Token
public String generateAccessToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + ACCESS_TOKEN_EXPIRATION))
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
// Generate Refresh Token
public String generateRefreshToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + REFRESH_TOKEN_EXPIRATION))
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
// Check if the Access Token is expired
public boolean isTokenExpired(String token) {
return getExpirationDateFromToken(token).before(new Date());
}
public Date getExpirationDateFromToken(String token) {
return Jwts.parserBuilder()
.setSigningKey(SECRET_KEY)
.build()
.parseClaimsJws(token)
.getBody()
.getExpiration();
}
public String extractUsername(String token) {
return Jwts.parserBuilder()
.setSigningKey(SECRET_KEY)
.build()
.parseClaimsJws(token)
.getBody()
.getSubject();
}
}
Explanation:
generateAccessToken
: এই ফাংশনটি ১৫ মিনিটের জন্য Access Token তৈরি করবে।generateRefreshToken
: এই ফাংশনটি ৭ দিনের জন্য Refresh Token তৈরি করবে।একটি API তৈরি করতে হবে যা Refresh Token গ্রহণ করে এবং নতুন Access Token প্রদান করবে। যখন একটি Access Token মেয়াদোত্তীর্ণ হয়ে যাবে, তখন Refresh Token ব্যবহার করে নতুন Access Token জেনারেট করা হবে।
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
public class AuthController {
@Autowired
private JwtUtil jwtUtil;
@PostMapping("/login")
public String login(@RequestBody AuthRequest authRequest) {
// Here you authenticate the user (omitting for brevity)
String accessToken = jwtUtil.generateAccessToken(authRequest.getUsername());
String refreshToken = jwtUtil.generateRefreshToken(authRequest.getUsername());
return "Access Token: " + accessToken + ", Refresh Token: " + refreshToken;
}
@PostMapping("/refresh-token")
public String refreshToken(@RequestBody RefreshTokenRequest refreshTokenRequest) {
String refreshToken = refreshTokenRequest.getRefreshToken();
// Verify the refresh token
if (jwtUtil.isTokenExpired(refreshToken)) {
throw new RuntimeException("Refresh token expired");
}
String username = jwtUtil.extractUsername(refreshToken);
String newAccessToken = jwtUtil.generateAccessToken(username);
return "New Access Token: " + newAccessToken;
}
}
class AuthRequest {
private String username;
private String password;
// Getters and Setters
}
class RefreshTokenRequest {
private String refreshToken;
// Getter and Setter
}
Explanation:
Spring Security-তে Token Expiration এবং Refresh Token Generation এর মাধ্যমে আপনি JWT Authentication-কে আরো নিরাপদ এবং ব্যবহারকারী-বান্ধব করতে পারেন।
Spring Security এর সাথে Refresh Token বাস্তবায়ন করতে আমরা নিম্নলিখিত পদক্ষেপ অনুসরণ করতে পারি:
প্রথমে, আমরা JWT ব্যবহার করে Access Token এবং Refresh Token তৈরি করব। Access Token মেয়াদ সীমিত এবং Refresh Token দীর্ঘ মেয়াদী থাকে।
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 ACCESS_TOKEN_EXPIRATION = 3600000; // 1 hour
private static final long REFRESH_TOKEN_EXPIRATION = 86400000; // 24 hours
// Access Token তৈরি
public static String generateAccessToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + ACCESS_TOKEN_EXPIRATION))
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
// Refresh Token তৈরি
public static String generateRefreshToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + REFRESH_TOKEN_EXPIRATION))
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
}
ব্যবহারকারী যখন তাদের Access Token এর মেয়াদ শেষ হয়ে যায়, তখন তারা Refresh Token পাঠায় এবং নতুন Access Token পেতে পারে।
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/auth")
public class AuthenticationController {
// Refresh Token দিয়ে নতুন Access Token তৈরি করা
@PostMapping("/refresh")
public ResponseEntity<?> refreshToken(@RequestBody TokenRefreshRequest request) {
String refreshToken = request.getRefreshToken();
// Refresh Token যাচাই করুন
if (JwtUtil.validateToken(refreshToken)) {
String username = JwtUtil.getUsernameFromToken(refreshToken);
String newAccessToken = JwtUtil.generateAccessToken(username);
return ResponseEntity.ok(new JwtResponse(newAccessToken));
} else {
return ResponseEntity.status(HttpStatus.FORBIDDEN).body("Invalid refresh token");
}
}
}
public class TokenRefreshRequest {
private String refreshToken;
// Getter এবং Setter
public String getRefreshToken() {
return refreshToken;
}
public void setRefreshToken(String refreshToken) {
this.refreshToken = refreshToken;
}
}
public class JwtResponse {
private String accessToken;
// Constructor, Getter এবং Setter
public JwtResponse(String accessToken) {
this.accessToken = accessToken;
}
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
}
Spring Security Configuration এর মধ্যে আমরা JWT Authentication Filter এবং JWT Refresh Token Filter তৈরি করতে পারি।
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import io.jsonwebtoken.Claims;
public class JwtAuthenticationFilter extends OncePerRequestFilter {
private static final String SECRET_KEY = "mySecretKey";
@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); // "Bearer " বাদ দিন
if (JwtUtil.validateToken(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);
}
}
public class JwtUtil {
private static final String SECRET_KEY = "mySecretKey";
public static Claims validateToken(String token) {
return Jwts.parser()
.setSigningKey(SECRET_KEY)
.parseClaimsJws(token)
.getBody();
}
public static String getUsernameFromToken(String token) {
return validateToken(token).getSubject();
}
}
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/auth/refresh").permitAll()
.anyRequest().authenticated()
.and()
.addFilter(new JwtAuthenticationFilter());
}
}
এভাবে Spring Security এ Refresh Token ইমপ্লিমেন্ট করা যায়, যা Access Token মেয়াদ শেষ হলে ব্যবহারকারীদের সহজেই সেশন পুনঃপ্রবিষ্ট করতে সহায়ক।
Read more
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Ducimus nihil, quo, quis minus aspernatur expedita, incidunt facilis aliquid inventore voluptate dolores accusantium laborum labore a dolorum dolore omnis qui? Consequuntur sed facilis repellendus corrupti amet in quibusdam ducimus illo autem, a praesentium.
1 hour ago
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Ducimus nihil, quo, quis minus aspernatur expedita, incidunt facilis aliquid inventore voluptate dolores accusantium laborum labore a dolorum dolore omnis qui? Consequuntur sed facilis repellendus corrupti amet in quibusdam ducimus illo autem, a praesentium.
1 hour ago
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Ducimus nihil, quo, quis minus aspernatur expedita, incidunt facilis aliquid inventore voluptate dolores accusantium laborum labore a dolorum dolore omnis qui? Consequuntur sed facilis repellendus corrupti amet in quibusdam ducimus illo autem, a praesentium.
1 hour ago
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Ducimus nihil, quo, quis minus aspernatur expedita, incidunt facilis aliquid inventore voluptate dolores accusantium laborum labore a dolorum dolore omnis qui? Consequuntur sed facilis repellendus corrupti amet in quibusdam ducimus illo autem, a praesentium.
1 hour ago
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Ducimus nihil, quo, quis minus aspernatur expedita, incidunt facilis aliquid inventore voluptate dolores accusantium laborum labore a dolorum dolore omnis qui? Consequuntur sed facilis repellendus corrupti amet in quibusdam ducimus illo autem, a praesentium.
1 hour ago
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Ducimus nihil, quo, quis minus aspernatur expedita, incidunt facilis aliquid inventore voluptate dolores accusantium laborum labore a dolorum dolore omnis qui? Consequuntur sed facilis repellendus corrupti amet in quibusdam ducimus illo autem, a praesentium.
1 hour ago
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Ducimus nihil, quo, quis minus aspernatur expedita, incidunt facilis aliquid inventore voluptate dolores accusantium laborum labore a dolorum dolore omnis qui? Consequuntur sed facilis repellendus corrupti amet in quibusdam ducimus illo autem, a praesentium.
1 hour ago
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Ducimus nihil, quo, quis minus aspernatur expedita, incidunt facilis aliquid inventore voluptate dolores accusantium laborum labore a dolorum dolore omnis qui? Consequuntur sed facilis repellendus corrupti amet in quibusdam ducimus illo autem, a praesentium.
1 hour ago
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Ducimus nihil, quo, quis minus aspernatur expedita, incidunt facilis aliquid inventore voluptate dolores accusantium laborum labore a dolorum dolore omnis qui? Consequuntur sed facilis repellendus corrupti amet in quibusdam ducimus illo autem, a praesentium.
1 hour ago
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Ducimus nihil, quo, quis minus aspernatur expedita, incidunt facilis aliquid inventore voluptate dolores accusantium laborum labore a dolorum dolore omnis qui? Consequuntur sed facilis repellendus corrupti amet in quibusdam ducimus illo autem, a praesentium.
1 hour ago