Skip to content

Commit 5ac91db

Browse files
committed
update
1 parent 2ef647c commit 5ac91db

25 files changed

+843
-6
lines changed

image/female.png

98 KB
Loading

image/male.png

64.7 KB
Loading

pom.xml

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,6 @@
3131
<artifactId>mysql-connector-j</artifactId>
3232
<scope>runtime</scope>
3333
</dependency>
34-
<dependency>
35-
<groupId>org.springframework.boot</groupId>
36-
<artifactId>spring-boot-starter-test</artifactId>
37-
<scope>test</scope>
38-
</dependency>
3934

4035
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
4136
<dependency>
@@ -52,7 +47,55 @@
5247
<version>2.0.1.Final</version>
5348
</dependency>
5449

50+
<dependency>
51+
<groupId>io.springfox</groupId>
52+
<artifactId>springfox-swagger2</artifactId>
53+
<version>2.6.1</version>
54+
</dependency>
55+
56+
<dependency>
57+
<groupId>io.springfox</groupId>
58+
<artifactId>springfox-swagger-ui</artifactId>
59+
<version>2.6.1</version>
60+
</dependency>
61+
62+
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-security -->
63+
<dependency>
64+
<groupId>org.springframework.boot</groupId>
65+
<artifactId>spring-boot-starter-security</artifactId>
66+
</dependency>
67+
68+
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-web -->
69+
<dependency>
70+
<groupId>org.springframework.security</groupId>
71+
<artifactId>spring-security-web</artifactId>
72+
<version>6.1.3</version>
73+
</dependency>
74+
75+
76+
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt -->
77+
<dependency>
78+
<groupId>io.jsonwebtoken</groupId>
79+
<artifactId>jjwt</artifactId>
80+
<version>0.9.1</version>
81+
</dependency>
5582

83+
<dependency>
84+
<groupId>org.springframework.boot</groupId>
85+
<artifactId>spring-boot-starter-test</artifactId>
86+
<scope>test</scope>
87+
<exclusions>
88+
<exclusion>
89+
<groupId>org.junit.vintage</groupId>
90+
<artifactId>junit-vintage-engine</artifactId>
91+
</exclusion>
92+
</exclusions>
93+
</dependency>
94+
<dependency>
95+
<groupId>org.springframework.security</groupId>
96+
<artifactId>spring-security-config</artifactId>
97+
<version>5.7.10</version>
98+
</dependency>
5699

57100
</dependencies>
58101

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,26 @@
11
package com.hoangtien2k3.ticketbookingapi;
22

3+
import org.springframework.beans.factory.annotation.Autowired;
34
import org.springframework.boot.SpringApplication;
5+
import org.springframework.boot.CommandLineRunner;
46
import org.springframework.boot.autoconfigure.SpringBootApplication;
7+
import org.springframework.security.crypto.password.PasswordEncoder;
8+
import springfox.documentation.swagger2.annotations.EnableSwagger2;
59

610
@SpringBootApplication
7-
public class TicketBookingApiApplication {
11+
@EnableSwagger2
12+
public class TicketBookingApiApplication implements CommandLineRunner{
13+
14+
@Autowired
15+
private PasswordEncoder passwordEncoder;
816

917
public static void main(String[] args) {
1018
SpringApplication.run(TicketBookingApiApplication.class, args);
1119
}
1220

21+
@Override
22+
public void run(String... args) throws Exception {
23+
System.out.println(passwordEncoder.encode("123456"));
24+
}
25+
1326
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.hoangtien2k3.ticketbookingapi.config;
2+
3+
import jakarta.servlet.ServletException;
4+
import jakarta.servlet.http.HttpServletRequest;
5+
import jakarta.servlet.http.HttpServletResponse;
6+
import org.springframework.security.core.AuthenticationException;
7+
import org.springframework.security.web.AuthenticationEntryPoint;
8+
9+
import java.io.IOException;
10+
import java.io.Serializable;
11+
12+
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint, Serializable {
13+
private static final long serialVersionUID = -7858869558953243875L;
14+
@Override
15+
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
16+
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
17+
}
18+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package com.hoangtien2k3.ticketbookingapi.config;
2+
3+
import com.hoangtien2k3.ticketbookingapi.service.JwtUserDetailsService;
4+
import io.jsonwebtoken.ExpiredJwtException;
5+
import jakarta.servlet.FilterChain;
6+
import jakarta.servlet.ServletException;
7+
import jakarta.servlet.http.HttpServletRequest;
8+
import jakarta.servlet.http.HttpServletResponse;
9+
import org.springframework.beans.factory.annotation.Autowired;
10+
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
11+
import org.springframework.security.core.context.SecurityContextHolder;
12+
import org.springframework.security.core.userdetails.UserDetails;
13+
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
14+
import org.springframework.stereotype.Component;
15+
import org.springframework.web.filter.OncePerRequestFilter;
16+
17+
import java.io.IOException;
18+
19+
@Component
20+
public class JwtRequestFilter extends OncePerRequestFilter {
21+
22+
@Autowired
23+
private JwtUserDetailsService jwtUserDetailsService;
24+
25+
private final JwtToken jwtTokenUtil;
26+
27+
public JwtRequestFilter(JwtToken jwtTokenUtil) {
28+
this.jwtTokenUtil = jwtTokenUtil;
29+
}
30+
31+
@Override
32+
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
33+
final String requestTokenHeader = httpServletRequest.getHeader("Authorization");
34+
35+
String username = null;
36+
37+
String jwtToken = null;
38+
39+
40+
if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer ")) {
41+
42+
jwtToken = requestTokenHeader.substring(7);
43+
44+
try {
45+
46+
username = jwtTokenUtil.getUsernameFromToken(jwtToken);
47+
48+
} catch (IllegalArgumentException e) {
49+
50+
System.out.println("Unable to get JWT Token");
51+
52+
} catch (ExpiredJwtException e) {
53+
54+
System.out.println("JWT Token has expired");
55+
56+
}
57+
58+
} else {
59+
60+
logger.warn("JWT Token does not begin with Bearer String");
61+
62+
}
63+
64+
65+
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
66+
67+
UserDetails userDetails = this.jwtUserDetailsService.loadUserByUsername(username);
68+
69+
70+
if (jwtTokenUtil.validateToken(jwtToken, userDetails)) {
71+
72+
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
73+
74+
userDetails, null, userDetails.getAuthorities());
75+
76+
usernamePasswordAuthenticationToken
77+
78+
.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest));
79+
80+
81+
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
82+
}
83+
}
84+
filterChain.doFilter(httpServletRequest, httpServletResponse);
85+
}
86+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package com.hoangtien2k3.ticketbookingapi.config;
2+
3+
import io.jsonwebtoken.Claims;
4+
import io.jsonwebtoken.Jwts;
5+
import io.jsonwebtoken.SignatureAlgorithm;
6+
import lombok.Value;
7+
import org.springframework.security.core.userdetails.UserDetails;
8+
import org.springframework.stereotype.Component;
9+
10+
import java.io.Serializable;
11+
import java.util.Date;
12+
import java.util.HashMap;
13+
import java.util.Map;
14+
import java.util.function.Function;
15+
16+
@Component
17+
public class JwtToken implements Serializable {
18+
// được sử dụng cho quá trình serialization và deserialization
19+
private static final long serialVersionUID = -2550185165626007488L;
20+
21+
// xác định thời gian hiệu lực của mã JWT, hiệu lực trong vòng 5h
22+
public static final long JWT_TOKEN_VALIDITY = 5 * 60 * 60;
23+
24+
@Value("${jwt.secret}")
25+
private String secret;
26+
27+
// Phương thức này trích xuất tên người dùng từ mã JWT
28+
public String getUsernameFromToken(String token) {
29+
return getClaimFromToken(token, Claims::getSubject);
30+
}
31+
32+
// Phương thức này trích xuất một claim (trường thông tin) từ mã JWT
33+
private <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
34+
final Claims claims = getAllClaimsFromToken(token);
35+
return claimsResolver.apply(claims);
36+
}
37+
38+
// Phương thức này trích xuất tất cả các claims từ mã JWT và trả về chúng dưới dạng đối tượng Claims.
39+
private Claims getAllClaimsFromToken(String token) {
40+
return Jwts.parser()
41+
.setSigningKey(secret)
42+
.parseClaimsJws(token)
43+
.getBody();
44+
}
45+
46+
private Boolean isTokenExpired(String token) {
47+
48+
final Date expiration = getExpirationDateFromToken(token);
49+
50+
return expiration.before(new Date());
51+
52+
}
53+
54+
private Date getExpirationDateFromToken(String token) {
55+
return getClaimFromToken(token, Claims::getExpiration);
56+
}
57+
58+
public String generateToken(UserDetails userDetails) {
59+
Map<String, Object> claims = new HashMap<>();
60+
return doGenerateToken(claims, userDetails.getUsername());
61+
}
62+
63+
64+
private String doGenerateToken(Map<String, Object> claims, String subject) {
65+
66+
return Jwts
67+
.builder()
68+
.setClaims(claims)
69+
.setSubject(subject)
70+
.setIssuedAt(new Date(System.currentTimeMillis()))
71+
.setExpiration(new Date(System.currentTimeMillis() + JWT_TOKEN_VALIDITY * 1000))
72+
.signWith(SignatureAlgorithm.HS512, secret).compact();
73+
74+
}
75+
76+
77+
public Boolean validateToken(String token, UserDetails userDetails) {
78+
79+
final String username = getUsernameFromToken(token);
80+
return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
81+
82+
}
83+
84+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package com.hoangtien2k3.ticketbookingapi.config;
2+
3+
import com.hoangtien2k3.ticketbookingapi.service.JwtUserDetailsService;
4+
import org.springframework.beans.factory.annotation.Autowired;
5+
import org.springframework.context.annotation.Bean;
6+
import org.springframework.context.annotation.Configuration;
7+
import org.springframework.security.authentication.AuthenticationManager;
8+
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
9+
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
10+
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
11+
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
12+
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
13+
import org.springframework.security.config.http.SessionCreationPolicy;
14+
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
15+
import org.springframework.security.crypto.password.PasswordEncoder;
16+
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
17+
18+
@Configuration
19+
@EnableWebSecurity
20+
@EnableGlobalMethodSecurity(prePostEnabled = true)
21+
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
22+
@Autowired
23+
private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
24+
25+
@Autowired
26+
private JwtUserDetailsService jwtUserDetailsService;
27+
28+
@Autowired
29+
private JwtRequestFilter jwtRequestFilter;
30+
31+
@Autowired
32+
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
33+
34+
auth.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoder());
35+
36+
}
37+
38+
@Bean
39+
public JwtAuthenticationEntryPoint jwtAuthenticationEntryPointBean() throws Exception{
40+
return new JwtAuthenticationEntryPoint();
41+
}
42+
43+
44+
@Bean
45+
public PasswordEncoder passwordEncoder() {
46+
return new BCryptPasswordEncoder();
47+
}
48+
49+
@Bean
50+
@Override
51+
public AuthenticationManager authenticationManagerBean() throws Exception {
52+
return super.authenticationManagerBean();
53+
54+
}
55+
56+
@Override
57+
protected void configure(HttpSecurity httpSecurity) throws Exception {
58+
59+
httpSecurity.csrf().disable()
60+
61+
.authorizeRequests()
62+
.antMatchers(
63+
"/authenticate",
64+
"/seat/{schedule_id}/seat-empty",
65+
"/movies/now",
66+
"/movies/future",
67+
"/schedule/**",
68+
"/user/register",
69+
"/user/login"
70+
).permitAll()
71+
//swagger
72+
.antMatchers("/v2/api-docs",
73+
"/configuration/ui",
74+
"/swagger-resources/**",
75+
"/configuration/security",
76+
"/swagger-ui.html",
77+
"/webjars/**"
78+
).permitAll().
79+
80+
anyRequest().authenticated()
81+
.and()
82+
.exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint)
83+
.and()
84+
.sessionManagement()
85+
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
86+
87+
httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
88+
89+
}
90+
}

0 commit comments

Comments
 (0)