20 posts
Project
Project List
Team Project
Personal Project
- [Stock information collector using Gemini - TodayStock](/manage/2023/09/18/Project.html#Stock information-collector using Gemini---todaystock)
- [Daily development learning worksheet - TOCO](/manage/2023/09/18/Project.html#daily-development learning-worksheet---toco)
Stock information collector using Gemini - TodayStock
Kotlin Spring Boot 3.3.4 JPA Kotlin JDSL Gradle 8.8 PostgreSQL 15.3 Docker Flyway GCP Compute Engine, Cloud SQL, Artifact Registry, Vertex AI API (Gemini Pro 1.5) Spring Rest API

When testing Postman, we confirmed that it returns 10 of the latest news contents, including one piece of additional information, as shown below.
Currently, the operation has been temporarily turned off.

2. Application of Kotlin JDSL query builder
I had a strong desire to apply Korea's open source with the DSL created by Line, and I liked the fact that I could develop in a more Kotlin-friendly way than QueryDSL. I chose it because there was no need to consider creating a separate metamodel and there were many reviews that it was compatible with JPA.
3. Other articles that record concerns and solutions that arose during the development process
- [🚴🏽 How do I take environment variables?]({{site.baseurl}}/devops/2023/05/08/DevOps.html#-Environment variables-How do I take them?)
Region-based chat service for developers - DevMingle

Alpine Linux 3.16 Java 17 Spring Boot 3.1.3 JPA Gradle 8.2.1 PostgreSQL 15.3 Redis MongoDB Flyway AWS EC2, S3

Additionally, development work was carried out by dividing the develop branch into API development units, using branches with feature, and then merging them back into the ````develop``` branch.
2. Token issuance and verification
Validation is verified using the access and refresh tokens entered as headers in the Token filter. At this time, if the access token has expired, the refresh token can be viewed and reissued without a separate refresh token issuance request. And the newly issued token is so that the new token is reflected in the response.
setAuthenticationTokens was processed.
TokenFilter.java
tokenProvider.validateToken(accessToken);
if(tokenProvider.expiredToken(accessToken) && !tokenProvider.expiredToken(refreshToken)){
tokenProvider.validateToken(refreshToken);
Map<String,String> map = tokenProvider.rebuildToken(refreshToken);
accessToken = map.get("accessToken");
refreshToken = map.get("refreshToken");
}
setSecurityContextHolder(accessToken);
tokenProvider.setAuthenticationTokens(response, accessToken, refreshToken);
filterChain.doFilter(request, response);Based on the value contained in the token, we put it in LoginUser, an implementation of UserDetails````, so that @AuthenticationPrincipal```` can be used at the Controller level as a Security Context Holder.
Even when a member's nickname or password is changed, the token will be reissued to reflect this and returned.
@PostMapping("/password/reset/confirm")
public ResponseEntity<ApiResponse> isRandomPassword(@AuthenticationPrincipal LoginUser loginUser){
boolean isRandomPassword = usersRepository.findIsRandomPasswordById(loginUser.getId());
return responseBuilder(isRandomPassword, HttpStatus.OK);
}3. Processing of URLs that do not require authentication
It is complicated to list all URLs that do not require authentication in the security config, and the code is not clean. Furthermore, if separate verification in the token filter is not required, URL duplication will occur.
Because unnecessary maintenance may occur in the process of updating the same URLs on both sides, I thought it would be better to manage them in one place, so I managed them separately in ``application-auth.yml. If you look at the detailed code, it is registered in application-auth.ymlas follows. URLs were classified into those withprefix(/api/v1)``` and those without.
url:
permit:
get:
- /
- /actuator/health
prefixGet:
- /categories
- /posts/**
prefixPost:
- /users/login
- /users
- /users/otp
- /users/nicknameAfterwards, these URLs were loaded into the Configuration list with priority over SecurityConfig.
Each list of get and prefixGet is composed of a single list with a prefix attached. In other words, it was separated into URLs to be mapped to GET and POST.
@ConfigurationProperties(prefix = "url.permit")And apply permitAll() to allow access without authentication in each SecurityConfig.
TokenFilter processed it to proceed to another filter without token verification.
Because the token validity is checked rather than the authentication process and the user information is entered into the ``Security Context Holder addFilterBefore allows the token verification process to precede ````UsernamePasswordAuthenticationFilter.
SecurityConfig.java
http.httpBasic(HttpBasicConfigurer::disable)
.cors(Customizer.withDefaults())
.csrf(CsrfConfigurer::disable)
.sessionManagement(config -> config.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.addFilterBefore(tokenFilter, UsernamePasswordAuthenticationFilter.class)
.authorizeHttpRequests(auth -> {
for (String url : urlProperties.getGet()) {
auth.requestMatchers("GET", url).permitAll();
}
for (String url : urlProperties.getPost()) {
auth.requestMatchers("POST", url).permitAll();
}
auth.anyRequest().authenticated();
})
.exceptionHandling(exception -> exception
.authenticationEntryPoint(customEntryPoint)
.accessDeniedHandler(customEntryPoint)
);TokenFilter.java
private boolean doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
boolean b = false;
String method = request.getMethod();
String url = request.getRequestURI();
if (("GET".equals(method) && matchUrl(urlProperties.getGet(), request))
|| ("POST".equals(method) && matchUrl(urlProperties.getPost(), request))) {
filterChain.doFilter(request, response);
b=true;
}
return b;
}
private boolean matchUrl(List<String> list, HttpServletRequest request) {
AntPathRequestMatcher matcher;
for (String str : list) {
matcher = new AntPathRequestMatcher(str);
if (matcher.matches(new HttpServletRequestWrapper(request))) {
return true;
}
}
return false;
}데일리 개발학습 학습지 - TOCO

Java 17 Spring Boot 3.0.1 JPA Gradle Querydsl MySQL JUnit5 JS

//: # (
)Comments
No comments yet. Be the first!