Project Structure:
SecurityConfig.java
package com.deepsingh44.springjwt_tutorial.config;
import com.deepsingh44.springjwt_tutorial.filter.JwtFilter;
import com.deepsingh44.springjwt_tutorial.service.
CustomUserDetailService;
import org.springframework.beans.factory.annotation.Autowired;
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.config.annotation
.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.
BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.
UsernamePasswordAuthenticationFilter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomUserDetailService customUserDetailService;
@Autowired
private JwtFilter jwtFilter;
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.userDetailsService(customUserDetailService).
passwordEncoder(passwordEncoder());
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@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().
anyRequest().
authenticated().
and().
sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
//Add filter to validate the tokens with every request.
http.addFilterBefore(jwtFilter,
UsernamePasswordAuthenticationFilter.class);
}
}
AuthenticationController.java
package com.deepsingh44.springjwt_tutorial.controller;
import com.deepsingh44.springjwt_tutorial.model.JwtRequest;
import com.deepsingh44.springjwt_tutorial.model.JwtResponse;
import com.deepsingh44.springjwt_tutorial.model.User;
import com.deepsingh44.springjwt_tutorial.service.
CustomUserDetailService;
import com.deepsingh44.springjwt_tutorial.utility.JwtUtility;
import lombok.extern.java.Log;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.
UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class AuthenticationController {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private JwtUtility jwtUtility;
@Autowired
private CustomUserDetailService customUserDetailService;
@PostMapping("/authenticate")
public ResponseEntity<?> authenticate(@RequestBody JwtRequest jwtRequest)
throws Exception {
try {
authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(jwtRequest.
getUsername(),
jwtRequest.getPassword()));
} catch (DisabledException disabledException) {
throw new Exception("USER_IS_DISABLE", disabledException);
} catch (BadCredentialsException badCredentialsException) {
throw new Exception("INVALID_USER_CREDENTIALS",
badCredentialsException);
}
final UserDetails userDetails = customUserDetailService.
loadUserByUsername(jwtRequest.getUsername());
final String token = jwtUtility.generateToken(userDetails);
return ResponseEntity.ok(new JwtResponse(token));
}
@PostMapping("/register")
public ResponseEntity<?> saveUser(@RequestBody User user)
throws Exception {
return ResponseEntity.ok(customUserDetailService.save(user));
}
@GetMapping("/home")
public String home(){
return "Welcome to home page";
}
}
JwtFilter.java
package com.deepsingh44.springjwt_tutorial.filter;
import com.deepsingh44.springjwt_tutorial.service.CustomUserDetailService;
import com.deepsingh44.springjwt_tutorial.utility.JwtUtility;
import io.jsonwebtoken.ExpiredJwtException;
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.web.authentication.
WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
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;
@Component
public class JwtFilter extends OncePerRequestFilter {
@Autowired
private CustomUserDetailService jwtUserDetailsService;
@Autowired
private JwtUtility jwtTokenUtility;
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
final String requestTokenHeader = request.getHeader("Authorization");
String username = null;
String jwtToken = null;
if (requestTokenHeader != null && requestTokenHeader.
startsWith("Bearer ")) {
jwtToken = requestTokenHeader.substring(7);
try {
username = jwtTokenUtility.getUsernameFromToken(jwtToken);
} catch (IllegalArgumentException e) {
System.out.println("Unable to get JWT Token");
} catch (ExpiredJwtException e) {
System.out.println("JWT Token has expired");
}
} else {
System.out.println("JWT Token does not begin with Bearer String");
}
if (username != null && SecurityContextHolder.
getContext().getAuthentication() == null) {
UserDetails userDetails = this.
jwtUserDetailsService.loadUserByUsername(username);
if (jwtTokenUtility.validateToken(jwtToken, userDetails)) {
UsernamePasswordAuthenticationToken
usernamePasswordAuthenticationToken
= new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
usernamePasswordAuthenticationToken
.setDetails(new WebAuthenticationDetailsSource().
buildDetails(request));
SecurityContextHolder.getContext().
setAuthentication(usernamePasswordAuthenticationToken);
}
}
chain.doFilter(request, response);
}
}
JwtRequest.java
package com.deepsingh44.springjwt_tutorial.model;
public class JwtRequest {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
JwtResponse.java
package com.deepsingh44.springjwt_tutorial.model;
public class JwtResponse {
private final String jwttoken;
public JwtResponse(String jwttoken) {
this.jwttoken = jwttoken;
}
public String getJwttoken() {
return jwttoken;
}
}
User.java
package com.deepsingh44.springjwt_tutorial.model;
import javax.persistence.*;
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String username;
private String password;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
UserRepository.java
package com.deepsingh44.springjwt_tutorial.repository;
import com.deepsingh44.springjwt_tutorial.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends JpaRepository<User,Long> {
User findByUsername(String username);
}
CustomUserDetailService.java
package com.deepsingh44.springjwt_tutorial.service;
import com.deepsingh44.springjwt_tutorial.model.User;
import com.deepsingh44.springjwt_tutorial.repository.
UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.
UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
@Service
public class CustomUserDetailService implements UserDetailsService {
@Autowired
private UserRepository userDao;
@Autowired
private PasswordEncoder bcryptEncoder;
@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
User user = userDao.findByUsername(username);
if (user == null) {
throw new
UsernameNotFoundException("User not found : " + username);
}
return new
org.springframework.security.core.userdetails.User(user.
getUsername(),user.getPassword(),
new ArrayList());
}
public User save(User user) {
User newUser = new User();
newUser.setUsername(user.getUsername());
newUser.setPassword(bcryptEncoder.encode(user.getPassword()));
return userDao.save(newUser);
}
}
JwtUtility.java
package com.deepsingh44.springjwt_tutorial.utility;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
@Component
public class JwtUtility implements Serializable {
public static final long JWT_TOKEN_VALIDITY = 2*60*60;
@Value("${jwt.secret}")
private String secret;
public String getUsernameFromToken(String token) {
return getClaimFromToken(token, Claims::getSubject);
}
public Date getIssuedAtDateFromToken(String token) {
return getClaimFromToken(token, Claims::getIssuedAt);
}
public Date getExpirationDateFromToken(String token) {
return getClaimFromToken(token, Claims::getExpiration);
}
public <T> T getClaimFromToken(String token,
Function<Claims, T> claimsResolver) {
final Claims claims = getAllClaimsFromToken(token);
return claimsResolver.apply(claims);
}
private Claims getAllClaimsFromToken(String token) {
return Jwts.parser().
setSigningKey(secret).
parseClaimsJws(token).getBody();
}
private Boolean isTokenExpired(String token) {
final Date expiration = getExpirationDateFromToken(token);
return expiration.
before(new Date());
}
private Boolean ignoreTokenExpiration(String token) {
return false;
}
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap();
return doGenerateToken(claims,
userDetails.getUsername());
}
private String doGenerateToken(Map<String, Object>
claims, String subject) {
return Jwts.builder().
setClaims(claims).setSubject(subject).
setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() +
JWT_TOKEN_VALIDITY*1000)).
signWith(SignatureAlgorithm.HS512, secret).compact();
}
public Boolean canTokenBeRefreshed(String token) {
return (!isTokenExpired(token) || ignoreTokenExpiration(token));
}
public Boolean validateToken(String token, UserDetails userDetails) {
final String username = getUsernameFromToken(token);
return (username.equals(userDetails.getUsername()) &&
!isTokenExpired(token));
}
}
SpringJwtTutorialApplication.java
package com.deepsingh44.springjwt_tutorial;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.
SpringBootApplication;
@SpringBootApplication
public class SpringJwtTutorialApplication {
public static void main(String[] args) {
SpringApplication.run(SpringJwtTutorialApplication.class, args);
}
}
application.properties
jwt.secret=thisisasecretkey
spring.datasource.url =jdbc:mysql://localhost:3306/mydatabase
spring.datasource.username =root
spring.datasource.password =root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.properties.hibernate.dialect =org.hibernate.dialect.MySQL5Dialect
spring.jpa.hibernate.ddl-auto =update
Output Screens:
No comments:
Post a Comment