From 958438737bfe870f954c0990fa4e79a9e2621fbc Mon Sep 17 00:00:00 2001 From: yennanliu Date: Fri, 20 Dec 2024 16:25:20 +0800 Subject: [PATCH 01/18] add redis dep, conf --- springBootBlog/pom.xml | 21 +++++++++++++++++++ .../src/main/resources/application.properties | 8 ++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/springBootBlog/pom.xml b/springBootBlog/pom.xml index 3da190e0e..675cc2ed8 100644 --- a/springBootBlog/pom.xml +++ b/springBootBlog/pom.xml @@ -124,6 +124,27 @@ test + + + + org.springframework.boot + spring-boot-starter-data-redis + + + + + org.springframework.data + spring-data-redis + 3.0.11 + + + + + org.apache.commons + commons-pool2 + 2.11.1 + + diff --git a/springBootBlog/src/main/resources/application.properties b/springBootBlog/src/main/resources/application.properties index 94727f22f..d32eb1da5 100644 --- a/springBootBlog/src/main/resources/application.properties +++ b/springBootBlog/src/main/resources/application.properties @@ -17,4 +17,10 @@ spring.security.oauth2.client.registration.github.clientId=8c3b3cfa5ba107d7ad25 spring.security.oauth2.client.registration.github.clientSecret= # google login # custom error html -server.error.path=/error \ No newline at end of file +server.error.path=/error + +# redis +spring.cache.type=redis +spring.redis.host=localhost +spring.redis.port=6379 +spring.redis.timeout=60000 \ No newline at end of file From 3b59a3182cc439a53fbd406551936a631c2a42eb Mon Sep 17 00:00:00 2001 From: yennanliu Date: Fri, 20 Dec 2024 16:28:30 +0800 Subject: [PATCH 02/18] add redis conf, add annotation --- .../java/com/yen/mdblog/BlogApplication.java | 2 ++ .../yen/mdblog/config/RedisCacheConfig.java | 27 +++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 springBootBlog/src/main/java/com/yen/mdblog/config/RedisCacheConfig.java diff --git a/springBootBlog/src/main/java/com/yen/mdblog/BlogApplication.java b/springBootBlog/src/main/java/com/yen/mdblog/BlogApplication.java index 8a137c626..dbdfad312 100644 --- a/springBootBlog/src/main/java/com/yen/mdblog/BlogApplication.java +++ b/springBootBlog/src/main/java/com/yen/mdblog/BlogApplication.java @@ -2,7 +2,9 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cache.annotation.EnableCaching; +@EnableCaching @SpringBootApplication public class BlogApplication { public static void main(String[] args) { diff --git a/springBootBlog/src/main/java/com/yen/mdblog/config/RedisCacheConfig.java b/springBootBlog/src/main/java/com/yen/mdblog/config/RedisCacheConfig.java new file mode 100644 index 000000000..68afe3fff --- /dev/null +++ b/springBootBlog/src/main/java/com/yen/mdblog/config/RedisCacheConfig.java @@ -0,0 +1,27 @@ +package com.yen.mdblog.config; + +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.EnableCaching; +//import org.springframework.cache.redis.RedisCacheManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; + +@Configuration +@EnableCaching +public class RedisCacheConfig { + + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate<>(); + template.setConnectionFactory(connectionFactory); + return template; + } + + @Bean + public CacheManager cacheManager(RedisConnectionFactory connectionFactory) { + return RedisCacheManager.builder(connectionFactory).build(); + } +} \ No newline at end of file From 721d3260d2fe0e8a6b102cd8ff596be1d048772c Mon Sep 17 00:00:00 2001 From: yennanliu Date: Fri, 20 Dec 2024 16:33:39 +0800 Subject: [PATCH 03/18] fix dep version, make app can run --- springBootBlog/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/springBootBlog/pom.xml b/springBootBlog/pom.xml index 675cc2ed8..7dbe29094 100644 --- a/springBootBlog/pom.xml +++ b/springBootBlog/pom.xml @@ -135,14 +135,14 @@ org.springframework.data spring-data-redis - 3.0.11 + org.apache.commons commons-pool2 - 2.11.1 + From d4a74c01a504df03256fa55617bcf4b752e5667b Mon Sep 17 00:00:00 2001 From: yennanliu Date: Fri, 20 Dec 2024 16:42:01 +0800 Subject: [PATCH 04/18] add cache to post service --- .../yen/mdblog/service/impl/PostServiceImpl.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/springBootBlog/src/main/java/com/yen/mdblog/service/impl/PostServiceImpl.java b/springBootBlog/src/main/java/com/yen/mdblog/service/impl/PostServiceImpl.java index 3452f7e5a..289d616f6 100644 --- a/springBootBlog/src/main/java/com/yen/mdblog/service/impl/PostServiceImpl.java +++ b/springBootBlog/src/main/java/com/yen/mdblog/service/impl/PostServiceImpl.java @@ -7,6 +7,7 @@ import java.util.List; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; @Service @@ -16,8 +17,11 @@ public class PostServiceImpl implements PostService { @Autowired PostMapper postMapper; @Override + @Cacheable(value = "authorId", key = "#authorId") public List getPostsById(Integer authorId) { - + // Simulate a time-consuming database operation + simulateDelay(); + System.out.println(">>> Query slow DB get post by userId"); return postMapper.findById(authorId); } @@ -51,4 +55,13 @@ public void updatePost(Post post) { // log.info(">>> updatePost : post = {}", post); postMapper.updatePost(post); } + + private void simulateDelay() { + try { + Thread.sleep(3000); // 3 seconds + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + } From 71eb258d843e41d201efe8fbd46375fd5f0ec0b1 Mon Sep 17 00:00:00 2001 From: yennanliu Date: Fri, 20 Dec 2024 16:46:26 +0800 Subject: [PATCH 05/18] update delay time --- .../main/java/com/yen/mdblog/service/impl/PostServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/springBootBlog/src/main/java/com/yen/mdblog/service/impl/PostServiceImpl.java b/springBootBlog/src/main/java/com/yen/mdblog/service/impl/PostServiceImpl.java index 289d616f6..bfa504153 100644 --- a/springBootBlog/src/main/java/com/yen/mdblog/service/impl/PostServiceImpl.java +++ b/springBootBlog/src/main/java/com/yen/mdblog/service/impl/PostServiceImpl.java @@ -58,7 +58,7 @@ public void updatePost(Post post) { private void simulateDelay() { try { - Thread.sleep(3000); // 3 seconds + Thread.sleep(10000); // 10 seconds } catch (InterruptedException e) { Thread.currentThread().interrupt(); } From bd7a469a4b4e2e7af0741a49eafbbbb044131f93 Mon Sep 17 00:00:00 2001 From: yennanliu Date: Sat, 21 Dec 2024 17:53:27 +0800 Subject: [PATCH 06/18] add cacheService --- .../com/yen/mdblog/service/CacheService.java | 28 +++++++++++++++++ .../mdblog/service/impl/PostServiceImpl.java | 31 ++++++++++++++----- 2 files changed, 51 insertions(+), 8 deletions(-) create mode 100644 springBootBlog/src/main/java/com/yen/mdblog/service/CacheService.java diff --git a/springBootBlog/src/main/java/com/yen/mdblog/service/CacheService.java b/springBootBlog/src/main/java/com/yen/mdblog/service/CacheService.java new file mode 100644 index 000000000..66d11f9fb --- /dev/null +++ b/springBootBlog/src/main/java/com/yen/mdblog/service/CacheService.java @@ -0,0 +1,28 @@ +package com.yen.mdblog.service; + +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +/** Cache service created by gpt */ +@Service +public class CacheService { + + /** + * Generic method to cache a result. + * + * @param cacheName the name of the cache + * @param key the cache key + * @param operation the operation to cache + * @param the type of the cached result + * @return the cached result + */ + @Cacheable(value = "#{cacheName}", key = "#{key}") + public T cacheResult(String cacheName, String key, CacheableOperation operation) { + return operation.execute(); + } + + @FunctionalInterface + public interface CacheableOperation { + T execute(); + } +} \ No newline at end of file diff --git a/springBootBlog/src/main/java/com/yen/mdblog/service/impl/PostServiceImpl.java b/springBootBlog/src/main/java/com/yen/mdblog/service/impl/PostServiceImpl.java index bfa504153..c4256d03f 100644 --- a/springBootBlog/src/main/java/com/yen/mdblog/service/impl/PostServiceImpl.java +++ b/springBootBlog/src/main/java/com/yen/mdblog/service/impl/PostServiceImpl.java @@ -3,6 +3,7 @@ import com.yen.mdblog.entity.Dto.SearchRequest; import com.yen.mdblog.entity.Po.Post; import com.yen.mdblog.mapper.PostMapper; +import com.yen.mdblog.service.CacheService; import com.yen.mdblog.service.PostService; import java.util.List; import lombok.extern.slf4j.Slf4j; @@ -16,14 +17,28 @@ public class PostServiceImpl implements PostService { @Autowired PostMapper postMapper; - @Override - @Cacheable(value = "authorId", key = "#authorId") - public List getPostsById(Integer authorId) { - // Simulate a time-consuming database operation - simulateDelay(); - System.out.println(">>> Query slow DB get post by userId"); - return postMapper.findById(authorId); - } + @Autowired private CacheService cacheService; + + @Override + @Cacheable(value = "authorId", key = "#authorId") + public List getPostsById(Integer authorId) { + // Simulate a time-consuming database operation + simulateDelay(); + System.out.println(">>> Query slow DB get post by userId"); + return postMapper.findById(authorId); + } +// +// @Override +// public List getPostsById(Integer authorId) { +// return cacheService.cacheResult( +// "authorId", +// "#authorId", +// () -> { +// simulateDelay(); +// System.out.println(">>> Query slow DB get post by userId"); +// return postMapper.findById(authorId); +// }); +// } @Override public List getAllPost() { From f1857248890087baa51334c0e014bea9e322cfff Mon Sep 17 00:00:00 2001 From: yennanliu Date: Sat, 21 Dec 2024 17:56:16 +0800 Subject: [PATCH 07/18] update blog readme ref --- springBootBlog/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/springBootBlog/README.md b/springBootBlog/README.md index 2df93d0d7..b38022bac 100644 --- a/springBootBlog/README.md +++ b/springBootBlog/README.md @@ -140,6 +140,9 @@ nohup java -jar target/mdblog-0.0.1-SNAPSHOT.jar & | `GET /` | GET |Swagger | http://localhost:8888/swagger-ui.html |Api page| +## App with `Redis cache` +- https://github.com/yennanliu/SpringPlayground/pull/192 + ## TODO - UI improvement From dcadac54dbe0d7f6020b629b20fa3c681313126c Mon Sep 17 00:00:00 2001 From: yennanliu Date: Wed, 1 Jan 2025 13:05:04 +0800 Subject: [PATCH 08/18] springSpotifyPlayList fix ref --- springSpotifyPlayList/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/springSpotifyPlayList/README.md b/springSpotifyPlayList/README.md index 51f308ea5..2e1d34974 100644 --- a/springSpotifyPlayList/README.md +++ b/springSpotifyPlayList/README.md @@ -176,8 +176,8 @@ docker logs - https://github.com/hardikSinghBehl/spotifyApiSpring/tree/master -- ML ref notebook - - https://github.com/yennanliu/SpringPlayground/blob/main/springSpotifyPlayList/doc/Spotify_ApI_call_demo.ipynb?fbclid=IwAR1ZhL081euAUCeB54kaMMNqCHBN1HnuLLTYpnpjNHAf4MMFW8VkgdP5N1o +- ML notebook + - https://github.com/yennanliu/SpringPlayground/tree/main/springSpotifyPlayList/nb - https://medium.com/@shruti.somankar/building-a-music-recommendation-system-using-spotify-api-and-python-f7418a21fa41 From c8cf64361d03be249e0194db6eea88180613d144 Mon Sep 17 00:00:00 2001 From: yennanliu Date: Sun, 16 Feb 2025 07:37:47 +0800 Subject: [PATCH 09/18] add SecurityDemo/ --- projects_advanced/SecurityDemo/.gitattributes | 2 + projects_advanced/SecurityDemo/.gitignore | 33 +++++++++ projects_advanced/SecurityDemo/pom.xml | 74 +++++++++++++++++++ .../SecurityDemo/SecurityDemoApplication.java | 13 ++++ .../src/main/resources/application.properties | 1 + .../SecurityDemoApplicationTests.java | 13 ++++ 6 files changed, 136 insertions(+) create mode 100644 projects_advanced/SecurityDemo/.gitattributes create mode 100644 projects_advanced/SecurityDemo/.gitignore create mode 100644 projects_advanced/SecurityDemo/pom.xml create mode 100644 projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/SecurityDemoApplication.java create mode 100644 projects_advanced/SecurityDemo/src/main/resources/application.properties create mode 100644 projects_advanced/SecurityDemo/src/test/java/com/yen/SecurityDemo/SecurityDemoApplicationTests.java diff --git a/projects_advanced/SecurityDemo/.gitattributes b/projects_advanced/SecurityDemo/.gitattributes new file mode 100644 index 000000000..3b41682ac --- /dev/null +++ b/projects_advanced/SecurityDemo/.gitattributes @@ -0,0 +1,2 @@ +/mvnw text eol=lf +*.cmd text eol=crlf diff --git a/projects_advanced/SecurityDemo/.gitignore b/projects_advanced/SecurityDemo/.gitignore new file mode 100644 index 000000000..549e00a2a --- /dev/null +++ b/projects_advanced/SecurityDemo/.gitignore @@ -0,0 +1,33 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/projects_advanced/SecurityDemo/pom.xml b/projects_advanced/SecurityDemo/pom.xml new file mode 100644 index 000000000..a503cfbdd --- /dev/null +++ b/projects_advanced/SecurityDemo/pom.xml @@ -0,0 +1,74 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.3.9-SNAPSHOT + + + com.yen + SecurityDemo + 0.0.1-SNAPSHOT + SecurityDemo + SecurityDemo project for Spring Boot + + + + + + + + + + + + + + + 17 + + + + org.springframework.boot + spring-boot-starter + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/snapshot + + false + + + + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/snapshot + + false + + + + + diff --git a/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/SecurityDemoApplication.java b/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/SecurityDemoApplication.java new file mode 100644 index 000000000..0e53ace26 --- /dev/null +++ b/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/SecurityDemoApplication.java @@ -0,0 +1,13 @@ +package com.yen.SecurityDemo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SecurityDemoApplication { + + public static void main(String[] args) { + SpringApplication.run(SecurityDemoApplication.class, args); + } + +} diff --git a/projects_advanced/SecurityDemo/src/main/resources/application.properties b/projects_advanced/SecurityDemo/src/main/resources/application.properties new file mode 100644 index 000000000..32a147bb2 --- /dev/null +++ b/projects_advanced/SecurityDemo/src/main/resources/application.properties @@ -0,0 +1 @@ +spring.application.name=SecurityDemo diff --git a/projects_advanced/SecurityDemo/src/test/java/com/yen/SecurityDemo/SecurityDemoApplicationTests.java b/projects_advanced/SecurityDemo/src/test/java/com/yen/SecurityDemo/SecurityDemoApplicationTests.java new file mode 100644 index 000000000..1dced9376 --- /dev/null +++ b/projects_advanced/SecurityDemo/src/test/java/com/yen/SecurityDemo/SecurityDemoApplicationTests.java @@ -0,0 +1,13 @@ +package com.yen.SecurityDemo; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class SecurityDemoApplicationTests { + + @Test + void contextLoads() { + } + +} From 27282eb97f3293c96361da69318bebc70700ffe7 Mon Sep 17 00:00:00 2001 From: yennanliu Date: Sun, 16 Feb 2025 07:48:58 +0800 Subject: [PATCH 10/18] update dep --- projects_advanced/SecurityDemo/pom.xml | 29 ++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/projects_advanced/SecurityDemo/pom.xml b/projects_advanced/SecurityDemo/pom.xml index a503cfbdd..af891c11c 100644 --- a/projects_advanced/SecurityDemo/pom.xml +++ b/projects_advanced/SecurityDemo/pom.xml @@ -29,6 +29,7 @@ 17 + org.springframework.boot @@ -40,6 +41,34 @@ spring-boot-starter-test test + + + + org.springframework.boot + spring-boot-starter-security + 3.3.4 + + + + + + + + + + org.springframework.boot + spring-boot-starter-web + + From 2acecfb31f6cbfe7beb10e5723929ef8d124a9ac Mon Sep 17 00:00:00 2001 From: yennanliu Date: Sun, 16 Feb 2025 08:14:06 +0800 Subject: [PATCH 11/18] fix pom, add config --- projects_advanced/SecurityDemo/pom.xml | 14 +--- .../SecurityDemo/config/SecurityConfig.java | 72 +++++++++++++++++++ 2 files changed, 74 insertions(+), 12 deletions(-) create mode 100644 projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/config/SecurityConfig.java diff --git a/projects_advanced/SecurityDemo/pom.xml b/projects_advanced/SecurityDemo/pom.xml index af891c11c..44e1f728f 100644 --- a/projects_advanced/SecurityDemo/pom.xml +++ b/projects_advanced/SecurityDemo/pom.xml @@ -14,20 +14,10 @@ SecurityDemo SecurityDemo project for Spring Boot - - - - - - - - - - - - 17 + 17 + 17 diff --git a/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/config/SecurityConfig.java b/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/config/SecurityConfig.java new file mode 100644 index 000000000..863df254e --- /dev/null +++ b/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/config/SecurityConfig.java @@ -0,0 +1,72 @@ +package com.yen.SecurityDemo.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.ProviderManager; +import org.springframework.security.authentication.dao.DaoAuthenticationProvider; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.core.userdetails.User; +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.SecurityFilterChain; + +import static org.springframework.security.config.Customizer.withDefaults; + +@Configuration +public class SecurityConfig { + +// @Bean +// public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { +// http +// .csrf(csrf -> csrf.disable()) +// .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) +// .authorizeHttpRequests(auth -> auth +// .requestMatchers("/api/auth/login").permitAll() +// .anyRequest().authenticated() +// ) +// .httpBasic(); +// return http.build(); +// } + + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http + .csrf(csrf -> csrf.disable()) + .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) + .authorizeHttpRequests(auth -> auth + .requestMatchers("/api/auth/login").permitAll() + .anyRequest().authenticated() + ) + .httpBasic(withDefaults()); // Use `withDefaults()` instead + return http.build(); + } + + @Bean + public AuthenticationManager authenticationManager(UserDetailsService userDetailsService, PasswordEncoder passwordEncoder) { + DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider(); + authProvider.setUserDetailsService(userDetailsService); + authProvider.setPasswordEncoder(passwordEncoder); + return new ProviderManager(authProvider); + } + + @Bean + public UserDetailsService userDetailsService() { + return username -> { + if ("user".equals(username)) { + return User.withUsername(username) + .password(passwordEncoder().encode("password")) + .roles("USER") + .build(); + } + throw new RuntimeException("User not found"); + }; + } + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } +} \ No newline at end of file From f0a10425a0ca9af94a23f02db41b84351c1ca30e Mon Sep 17 00:00:00 2001 From: yennanliu Date: Sun, 16 Feb 2025 08:17:01 +0800 Subject: [PATCH 12/18] add code --- .../controller/AuthController.java | 37 +++++++++++++ .../SecurityDemo/filter/JwtAuthFilter.java | 55 +++++++++++++++++++ .../com/yen/SecurityDemo/util/JwtUtil.java | 47 ++++++++++++++++ 3 files changed, 139 insertions(+) create mode 100644 projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/controller/AuthController.java create mode 100644 projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/filter/JwtAuthFilter.java create mode 100644 projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/util/JwtUtil.java diff --git a/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/controller/AuthController.java b/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/controller/AuthController.java new file mode 100644 index 000000000..13d7aa058 --- /dev/null +++ b/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/controller/AuthController.java @@ -0,0 +1,37 @@ +//package com.yen.SecurityDemo.controller; +// +//import org.springframework.http.ResponseEntity; +//import org.springframework.security.authentication.AuthenticationManager; +//import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +//import org.springframework.security.core.userdetails.UserDetails; +//import org.springframework.security.core.userdetails.UserDetailsService; +//import org.springframework.web.bind.annotation.*; +// +//import java.util.Map; +// +//@RestController +//@RequestMapping("/api/auth") +//public class AuthController { +// +// private final AuthenticationManager authenticationManager; +// //private final JwtUtil jwtUtil; +// private final UserDetailsService userDetailsService; +// +// public AuthController(AuthenticationManager authenticationManager, JwtUtil jwtUtil, UserDetailsService userDetailsService) { +// this.authenticationManager = authenticationManager; +// this.jwtUtil = jwtUtil; +// this.userDetailsService = userDetailsService; +// } +// +// @PostMapping("/login") +// public ResponseEntity login(@RequestBody Map credentials) { +// String username = credentials.get("username"); +// String password = credentials.get("password"); +// +// authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password)); +// UserDetails userDetails = userDetailsService.loadUserByUsername(username); +// //String token = jwtUtil.generateToken(userDetails.getUsername()); +// +// return ResponseEntity.ok(Map.of("token", token)); +// } +//} \ No newline at end of file diff --git a/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/filter/JwtAuthFilter.java b/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/filter/JwtAuthFilter.java new file mode 100644 index 000000000..fbf7fab5c --- /dev/null +++ b/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/filter/JwtAuthFilter.java @@ -0,0 +1,55 @@ +//package com.yen.SecurityDemo.filter; +// +//import jakarta.servlet.FilterChain; +//import jakarta.servlet.ServletException; +//import jakarta.servlet.http.HttpServletRequest; +//import jakarta.servlet.http.HttpServletResponse; +//import org.springframework.security.core.context.SecurityContextHolder; +//import org.springframework.security.core.userdetails.UserDetails; +//import org.springframework.security.core.userdetails.UserDetailsService; +//import org.springframework.security.web.authentication.UsernamePasswordAuthenticationToken; +//import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; +//import org.springframework.stereotype.Component; +//import org.springframework.web.filter.OncePerRequestFilter; +// +//import java.io.IOException; +// +//@Component +//public class JwtAuthFilter extends OncePerRequestFilter { +// +// private final JwtUtil jwtUtil; +// private final UserDetailsService userDetailsService; +// +// public JwtAuthFilter(JwtUtil jwtUtil, UserDetailsService userDetailsService) { +// this.jwtUtil = jwtUtil; +// this.userDetailsService = userDetailsService; +// } +// +// @Override +// protected void doFilterInternal(HttpServletRequest request, +// HttpServletResponse response, +// FilterChain filterChain) throws ServletException, IOException { +// +// String authHeader = request.getHeader("Authorization"); +// if (authHeader == null || !authHeader.startsWith("Bearer ")) { +// filterChain.doFilter(request, response); +// return; +// } +// +// String token = authHeader.substring(7); +// String username = jwtUtil.extractUsername(token); +// +// if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { +// UserDetails userDetails = userDetailsService.loadUserByUsername(username); +// +// if (jwtUtil.validateToken(token, userDetails.getUsername())) { +// UsernamePasswordAuthenticationToken authToken = +// new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); +// authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); +// SecurityContextHolder.getContext().setAuthentication(authToken); +// } +// } +// +// filterChain.doFilter(request, response); +// } +//} \ No newline at end of file diff --git a/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/util/JwtUtil.java b/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/util/JwtUtil.java new file mode 100644 index 000000000..137ae6f86 --- /dev/null +++ b/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/util/JwtUtil.java @@ -0,0 +1,47 @@ +//package com.yen.SecurityDemo.util; +// +//import io.jsonwebtoken.Claims; +//import io.jsonwebtoken.Jwts; +//import io.jsonwebtoken.SignatureAlgorithm; +//import org.springframework.stereotype.Component; +// +//import java.util.Date; +//import java.util.function.Function; +// +//@Component +//public class JwtUtil { +// private static final String SECRET_KEY = "your_secret_key"; +// +// public String generateToken(String username) { +// return Jwts.builder() +// .setSubject(username) +// .setIssuedAt(new Date()) +// .setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60)) // 1 hour +// .signWith(SignatureAlgorithm.HS256, SECRET_KEY) +// .compact(); +// } +// +// public String extractUsername(String token) { +// return extractClaim(token, Claims::getSubject); +// } +// +// public Date extractExpiration(String token) { +// return extractClaim(token, Claims::getExpiration); +// } +// +// public T extractClaim(String token, Function claimsResolver) { +// final Claims claims = Jwts.parser() +// .setSigningKey(SECRET_KEY) +// .parseClaimsJws(token) +// .getBody(); +// return claimsResolver.apply(claims); +// } +// +// public boolean validateToken(String token, String username) { +// return (username.equals(extractUsername(token)) && !isTokenExpired(token)); +// } +// +// private boolean isTokenExpired(String token) { +// return extractExpiration(token).before(new Date()); +// } +//} \ No newline at end of file From 062bfef5b3ffc1c388fc1d56c1d11bdcfa07153c Mon Sep 17 00:00:00 2001 From: yennanliu Date: Sun, 16 Feb 2025 08:20:51 +0800 Subject: [PATCH 13/18] fix dep, enable util, controller --- projects_advanced/SecurityDemo/pom.xml | 9 +- .../controller/AuthController.java | 75 +++++++-------- .../com/yen/SecurityDemo/util/JwtUtil.java | 94 +++++++++---------- 3 files changed, 93 insertions(+), 85 deletions(-) diff --git a/projects_advanced/SecurityDemo/pom.xml b/projects_advanced/SecurityDemo/pom.xml index 44e1f728f..0ac47132b 100644 --- a/projects_advanced/SecurityDemo/pom.xml +++ b/projects_advanced/SecurityDemo/pom.xml @@ -51,9 +51,16 @@ - + + + + io.jsonwebtoken + jjwt + 0.9.1 + + org.springframework.boot spring-boot-starter-web diff --git a/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/controller/AuthController.java b/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/controller/AuthController.java index 13d7aa058..c84b8ea16 100644 --- a/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/controller/AuthController.java +++ b/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/controller/AuthController.java @@ -1,37 +1,38 @@ -//package com.yen.SecurityDemo.controller; -// -//import org.springframework.http.ResponseEntity; -//import org.springframework.security.authentication.AuthenticationManager; -//import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -//import org.springframework.security.core.userdetails.UserDetails; -//import org.springframework.security.core.userdetails.UserDetailsService; -//import org.springframework.web.bind.annotation.*; -// -//import java.util.Map; -// -//@RestController -//@RequestMapping("/api/auth") -//public class AuthController { -// -// private final AuthenticationManager authenticationManager; -// //private final JwtUtil jwtUtil; -// private final UserDetailsService userDetailsService; -// -// public AuthController(AuthenticationManager authenticationManager, JwtUtil jwtUtil, UserDetailsService userDetailsService) { -// this.authenticationManager = authenticationManager; -// this.jwtUtil = jwtUtil; -// this.userDetailsService = userDetailsService; -// } -// -// @PostMapping("/login") -// public ResponseEntity login(@RequestBody Map credentials) { -// String username = credentials.get("username"); -// String password = credentials.get("password"); -// -// authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password)); -// UserDetails userDetails = userDetailsService.loadUserByUsername(username); -// //String token = jwtUtil.generateToken(userDetails.getUsername()); -// -// return ResponseEntity.ok(Map.of("token", token)); -// } -//} \ No newline at end of file +package com.yen.SecurityDemo.controller; + +import com.yen.SecurityDemo.util.JwtUtil; +import org.springframework.http.ResponseEntity; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.web.bind.annotation.*; + +import java.util.Map; + +@RestController +@RequestMapping("/api/auth") +public class AuthController { + + private final AuthenticationManager authenticationManager; + private final JwtUtil jwtUtil; + private final UserDetailsService userDetailsService; + + + public AuthController(AuthenticationManager authenticationManager, JwtUtil jwtUtil, UserDetailsService userDetailsService) { + this.authenticationManager = authenticationManager; + this.jwtUtil = jwtUtil; + this.userDetailsService = userDetailsService; + } + + @PostMapping("/login") + public ResponseEntity login(@RequestBody Map credentials) { + String username = credentials.get("username"); + String password = credentials.get("password"); + + authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password)); + UserDetails userDetails = userDetailsService.loadUserByUsername(username); + String token = jwtUtil.generateToken(userDetails.getUsername()); + return ResponseEntity.ok(Map.of("token", token)); + } +} \ No newline at end of file diff --git a/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/util/JwtUtil.java b/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/util/JwtUtil.java index 137ae6f86..dcd2dd0e8 100644 --- a/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/util/JwtUtil.java +++ b/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/util/JwtUtil.java @@ -1,47 +1,47 @@ -//package com.yen.SecurityDemo.util; -// -//import io.jsonwebtoken.Claims; -//import io.jsonwebtoken.Jwts; -//import io.jsonwebtoken.SignatureAlgorithm; -//import org.springframework.stereotype.Component; -// -//import java.util.Date; -//import java.util.function.Function; -// -//@Component -//public class JwtUtil { -// private static final String SECRET_KEY = "your_secret_key"; -// -// public String generateToken(String username) { -// return Jwts.builder() -// .setSubject(username) -// .setIssuedAt(new Date()) -// .setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60)) // 1 hour -// .signWith(SignatureAlgorithm.HS256, SECRET_KEY) -// .compact(); -// } -// -// public String extractUsername(String token) { -// return extractClaim(token, Claims::getSubject); -// } -// -// public Date extractExpiration(String token) { -// return extractClaim(token, Claims::getExpiration); -// } -// -// public T extractClaim(String token, Function claimsResolver) { -// final Claims claims = Jwts.parser() -// .setSigningKey(SECRET_KEY) -// .parseClaimsJws(token) -// .getBody(); -// return claimsResolver.apply(claims); -// } -// -// public boolean validateToken(String token, String username) { -// return (username.equals(extractUsername(token)) && !isTokenExpired(token)); -// } -// -// private boolean isTokenExpired(String token) { -// return extractExpiration(token).before(new Date()); -// } -//} \ No newline at end of file +package com.yen.SecurityDemo.util; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import org.springframework.stereotype.Component; + +import java.util.Date; +import java.util.function.Function; + +@Component +public class JwtUtil { + private static final String SECRET_KEY = "your_secret_key"; + + public String generateToken(String username) { + return Jwts.builder() + .setSubject(username) + .setIssuedAt(new Date()) + .setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60)) // 1 hour + .signWith(SignatureAlgorithm.HS256, SECRET_KEY) + .compact(); + } + + public String extractUsername(String token) { + return extractClaim(token, Claims::getSubject); + } + + public Date extractExpiration(String token) { + return extractClaim(token, Claims::getExpiration); + } + + public T extractClaim(String token, Function claimsResolver) { + final Claims claims = Jwts.parser() + .setSigningKey(SECRET_KEY) + .parseClaimsJws(token) + .getBody(); + return claimsResolver.apply(claims); + } + + public boolean validateToken(String token, String username) { + return (username.equals(extractUsername(token)) && !isTokenExpired(token)); + } + + private boolean isTokenExpired(String token) { + return extractExpiration(token).before(new Date()); + } +} \ No newline at end of file From fe8022086f59331b4dc2801658ea009b640a239b Mon Sep 17 00:00:00 2001 From: yennanliu Date: Sun, 16 Feb 2025 08:28:49 +0800 Subject: [PATCH 14/18] fix dep, jwtAuthFilter --- .../SecurityDemo/filter/JwtAuthFilter.java | 55 ------------------ .../filter/JwtAuthenticationFilter.java | 56 +++++++++++++++++++ 2 files changed, 56 insertions(+), 55 deletions(-) delete mode 100644 projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/filter/JwtAuthFilter.java create mode 100644 projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/filter/JwtAuthenticationFilter.java diff --git a/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/filter/JwtAuthFilter.java b/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/filter/JwtAuthFilter.java deleted file mode 100644 index fbf7fab5c..000000000 --- a/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/filter/JwtAuthFilter.java +++ /dev/null @@ -1,55 +0,0 @@ -//package com.yen.SecurityDemo.filter; -// -//import jakarta.servlet.FilterChain; -//import jakarta.servlet.ServletException; -//import jakarta.servlet.http.HttpServletRequest; -//import jakarta.servlet.http.HttpServletResponse; -//import org.springframework.security.core.context.SecurityContextHolder; -//import org.springframework.security.core.userdetails.UserDetails; -//import org.springframework.security.core.userdetails.UserDetailsService; -//import org.springframework.security.web.authentication.UsernamePasswordAuthenticationToken; -//import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; -//import org.springframework.stereotype.Component; -//import org.springframework.web.filter.OncePerRequestFilter; -// -//import java.io.IOException; -// -//@Component -//public class JwtAuthFilter extends OncePerRequestFilter { -// -// private final JwtUtil jwtUtil; -// private final UserDetailsService userDetailsService; -// -// public JwtAuthFilter(JwtUtil jwtUtil, UserDetailsService userDetailsService) { -// this.jwtUtil = jwtUtil; -// this.userDetailsService = userDetailsService; -// } -// -// @Override -// protected void doFilterInternal(HttpServletRequest request, -// HttpServletResponse response, -// FilterChain filterChain) throws ServletException, IOException { -// -// String authHeader = request.getHeader("Authorization"); -// if (authHeader == null || !authHeader.startsWith("Bearer ")) { -// filterChain.doFilter(request, response); -// return; -// } -// -// String token = authHeader.substring(7); -// String username = jwtUtil.extractUsername(token); -// -// if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { -// UserDetails userDetails = userDetailsService.loadUserByUsername(username); -// -// if (jwtUtil.validateToken(token, userDetails.getUsername())) { -// UsernamePasswordAuthenticationToken authToken = -// new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); -// authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); -// SecurityContextHolder.getContext().setAuthentication(authToken); -// } -// } -// -// filterChain.doFilter(request, response); -// } -//} \ No newline at end of file diff --git a/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/filter/JwtAuthenticationFilter.java b/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/filter/JwtAuthenticationFilter.java new file mode 100644 index 000000000..14f92ef1a --- /dev/null +++ b/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/filter/JwtAuthenticationFilter.java @@ -0,0 +1,56 @@ +package com.yen.SecurityDemo.filter; + +import com.yen.SecurityDemo.util.JwtUtil; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +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.security.web.authentication.WebAuthenticationDetailsSource; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; +import java.io.IOException; + +@Component +public class JwtAuthenticationFilter extends OncePerRequestFilter { + + private final JwtUtil jwtUtil; + private final UserDetailsService userDetailsService; + + public JwtAuthenticationFilter(JwtUtil jwtUtil, UserDetailsService userDetailsService) { + this.jwtUtil = jwtUtil; + this.userDetailsService = userDetailsService; + } + + @Override + protected void doFilterInternal(HttpServletRequest request, + HttpServletResponse response, + FilterChain filterChain) throws ServletException, IOException { + + String authHeader = request.getHeader("Authorization"); + if (authHeader == null || !authHeader.startsWith("Bearer ")) { + filterChain.doFilter(request, response); + return; + } + + String token = authHeader.substring(7); + String username = jwtUtil.extractUsername(token); + + if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { + UserDetails userDetails = userDetailsService.loadUserByUsername(username); + + if (jwtUtil.validateToken(token, String.valueOf(userDetails))) { + UsernamePasswordAuthenticationToken authToken = + new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); + + authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + SecurityContextHolder.getContext().setAuthentication(authToken); + } + } + + filterChain.doFilter(request, response); + } +} \ No newline at end of file From f4b8ef41f6b41e9ceb76c7a8f6919ca7899c58c6 Mon Sep 17 00:00:00 2001 From: yennanliu Date: Sun, 16 Feb 2025 08:32:34 +0800 Subject: [PATCH 15/18] rename file, update config, make app can run --- .../com/yen/SecurityDemo/config/SecurityConfig.java | 10 +++++++--- ...JwtAuthenticationFilter.java => JwtAuthFilter.java} | 4 ++-- 2 files changed, 9 insertions(+), 5 deletions(-) rename projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/filter/{JwtAuthenticationFilter.java => JwtAuthFilter.java} (93%) diff --git a/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/config/SecurityConfig.java b/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/config/SecurityConfig.java index 863df254e..d99f79c6d 100644 --- a/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/config/SecurityConfig.java +++ b/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/config/SecurityConfig.java @@ -1,5 +1,6 @@ package com.yen.SecurityDemo.config; +import com.yen.SecurityDemo.filter.JwtAuthFilter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; @@ -12,6 +13,7 @@ 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; import static org.springframework.security.config.Customizer.withDefaults; @@ -27,12 +29,12 @@ public class SecurityConfig { // .requestMatchers("/api/auth/login").permitAll() // .anyRequest().authenticated() // ) -// .httpBasic(); +// .httpBasic(withDefaults()); // Use `withDefaults()` instead // return http.build(); // } @Bean - public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + public SecurityFilterChain securityFilterChain(HttpSecurity http, JwtAuthFilter jwtAuthFilter) throws Exception { http .csrf(csrf -> csrf.disable()) .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) @@ -40,7 +42,8 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti .requestMatchers("/api/auth/login").permitAll() .anyRequest().authenticated() ) - .httpBasic(withDefaults()); // Use `withDefaults()` instead + .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class); + return http.build(); } @@ -69,4 +72,5 @@ public UserDetailsService userDetailsService() { public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } + } \ No newline at end of file diff --git a/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/filter/JwtAuthenticationFilter.java b/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/filter/JwtAuthFilter.java similarity index 93% rename from projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/filter/JwtAuthenticationFilter.java rename to projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/filter/JwtAuthFilter.java index 14f92ef1a..735732b85 100644 --- a/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/filter/JwtAuthenticationFilter.java +++ b/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/filter/JwtAuthFilter.java @@ -15,12 +15,12 @@ import java.io.IOException; @Component -public class JwtAuthenticationFilter extends OncePerRequestFilter { +public class JwtAuthFilter extends OncePerRequestFilter { private final JwtUtil jwtUtil; private final UserDetailsService userDetailsService; - public JwtAuthenticationFilter(JwtUtil jwtUtil, UserDetailsService userDetailsService) { + public JwtAuthFilter(JwtUtil jwtUtil, UserDetailsService userDetailsService) { this.jwtUtil = jwtUtil; this.userDetailsService = userDetailsService; } From a1c61b4fb0bc6dda62795f45094f846832f58464 Mon Sep 17 00:00:00 2001 From: yennanliu Date: Sun, 16 Feb 2025 08:37:14 +0800 Subject: [PATCH 16/18] add testController, readme --- projects_advanced/SecurityDemo/README.md | 14 +++++++++++ .../controller/TestController.java | 23 +++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 projects_advanced/SecurityDemo/README.md create mode 100644 projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/controller/TestController.java diff --git a/projects_advanced/SecurityDemo/README.md b/projects_advanced/SecurityDemo/README.md new file mode 100644 index 000000000..c5635f55f --- /dev/null +++ b/projects_advanced/SecurityDemo/README.md @@ -0,0 +1,14 @@ +# Spring Security Demo + +## Run + +```bash + +# 1) + +curl -X GET http://localhost:8080/api/test/public +``` + +## Dep + +- Spring Security 6 \ No newline at end of file diff --git a/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/controller/TestController.java b/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/controller/TestController.java new file mode 100644 index 000000000..ede6cbf94 --- /dev/null +++ b/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/controller/TestController.java @@ -0,0 +1,23 @@ +package com.yen.SecurityDemo.controller; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.security.core.userdetails.UserDetails; + +@RestController +@RequestMapping("/api/test") +public class TestController { + + @GetMapping("/public") + public String publicEndpoint() { + return "This is a public endpoint. No authentication needed!"; + } + + @GetMapping("/private") + public String privateEndpoint(@AuthenticationPrincipal UserDetails userDetails) { + return "Hello, " + userDetails.getUsername() + "! This is a protected endpoint."; + } + +} \ No newline at end of file From c6bff2243d69a7c9e9c368b70843a71443a1a9e1 Mon Sep 17 00:00:00 2001 From: yennanliu Date: Fri, 28 Feb 2025 18:57:26 +0800 Subject: [PATCH 17/18] add .gemini/config.yaml --- .gemini/config.yaml | 9 +++++++++ .../com/yen/SecurityDemo/SecurityDemoApplication.java | 1 + 2 files changed, 10 insertions(+) create mode 100644 .gemini/config.yaml diff --git a/.gemini/config.yaml b/.gemini/config.yaml new file mode 100644 index 000000000..acf25d486 --- /dev/null +++ b/.gemini/config.yaml @@ -0,0 +1,9 @@ +have_fun: true +code_review: + disable: false + comment_severity_threshold: MEDIUM + max_review_comments: -1 + pull_request_opened: + help: false + summary: true + code_review: true diff --git a/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/SecurityDemoApplication.java b/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/SecurityDemoApplication.java index 0e53ace26..9458684a4 100644 --- a/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/SecurityDemoApplication.java +++ b/projects_advanced/SecurityDemo/src/main/java/com/yen/SecurityDemo/SecurityDemoApplication.java @@ -7,6 +7,7 @@ public class SecurityDemoApplication { public static void main(String[] args) { + SpringApplication.run(SecurityDemoApplication.class, args); } From 4ef150f8c871c56f79a9c1aba918527258990d78 Mon Sep 17 00:00:00 2001 From: yennanliu Date: Fri, 28 Feb 2025 19:02:16 +0800 Subject: [PATCH 18/18] update --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index fee4b4c66..b3b7db9e8 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ - [springBasics](https://github.com/yennanliu/SpringPlayground/tree/main/projects_basic) : Basic Spring project demo + ## Structure