Skip to content

Commit 47fdcbb

Browse files
committed
fix: write just one time response
1 parent 39fcb86 commit 47fdcbb

File tree

7 files changed

+236
-224
lines changed

7 files changed

+236
-224
lines changed

.docker/.env.example

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,6 @@ SMTP_USERNAME=user@gmail
2828
SMTP_PASSWORD=secret
2929

3030
# swagger
31-
SWAGGER_URL=/docs
31+
SWAGGER_URL=/docs
32+
SWAGGER_USERNAME=
33+
SWAGGER_PASSWORD=

.docker/docker-compose.dev.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ services:
6262

6363
# swagger
6464
SWAGGER_URL: ${SWAGGER_URL}
65+
SWAGGER_USERNAME: ${SWAGGER_USERNAME}
66+
SWAGGER_PASSWORD: ${SWAGGER_PASSWORD}
6567
volumes:
6668
- ../api:/app
6769
- ./.volumes/maven:/root/.m2

api/src/main/java/com/github/throyer/common/springboot/configurations/SpringSecurityConfiguration.java

Lines changed: 92 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,13 @@
1313
import static com.github.throyer.common.springboot.constants.SECURITY.TOKEN_SECRET;
1414
import static com.github.throyer.common.springboot.constants.SECURITY.USERNAME_PARAMETER;
1515
import static com.github.throyer.common.springboot.utils.Responses.forbidden;
16-
import static java.util.Optional.ofNullable;
1716
import static org.springframework.http.HttpMethod.GET;
1817
import static org.springframework.http.HttpMethod.POST;
1918
import static org.springframework.security.config.http.SessionCreationPolicy.STATELESS;
2019

2120
import java.util.List;
22-
import java.util.Optional;
2321
import java.util.stream.Stream;
2422

25-
import com.github.throyer.common.springboot.domain.session.service.SessionService;
26-
import com.github.throyer.common.springboot.middlewares.AuthorizationMiddleware;
27-
2823
import org.springframework.beans.factory.annotation.Autowired;
2924
import org.springframework.beans.factory.annotation.Value;
3025
import org.springframework.context.annotation.Bean;
@@ -39,10 +34,12 @@
3934
import org.springframework.security.web.SecurityFilterChain;
4035
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
4136
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
42-
import org.springframework.stereotype.Component;
4337
import org.springframework.web.cors.CorsConfiguration;
4438

45-
@Component
39+
import com.github.throyer.common.springboot.domain.session.service.SessionService;
40+
import com.github.throyer.common.springboot.middlewares.AuthorizationMiddleware;
41+
import com.github.throyer.common.springboot.utils.Strings;
42+
4643
@Configuration
4744
@EnableWebSecurity
4845
@EnableGlobalMethodSecurity(prePostEnabled = true)
@@ -51,132 +48,130 @@ public class SpringSecurityConfiguration {
5148
private final SessionService sessionService;
5249
private final AuthorizationMiddleware filter;
5350

54-
public static String SWAGGER_USERNAME;
55-
public static String SWAGGER_PASSWORD;
51+
public static String SWAGGER_USERNAME = null;
52+
public static String SWAGGER_PASSWORD = null;
5653

5754
@Autowired
5855
public SpringSecurityConfiguration(
5956
SessionService sessionService,
60-
AuthorizationMiddleware filter
57+
AuthorizationMiddleware filter,
58+
@Value("${swagger.username}") String username,
59+
@Value("${swagger.password}") String password
6160
) {
62-
this.sessionService = sessionService;
63-
this.filter = filter;
61+
this.sessionService = sessionService;
62+
this.filter = filter;
63+
64+
SpringSecurityConfiguration.SWAGGER_USERNAME = username;
65+
SpringSecurityConfiguration.SWAGGER_PASSWORD = password;
6466
}
6567

6668
@Autowired
67-
protected void globalConfiguration(
68-
AuthenticationManagerBuilder authentication,
69-
@Value("${swagger.username}") String username,
70-
@Value("${swagger.password}") String password
71-
) throws Exception {
72-
SpringSecurityConfiguration.SWAGGER_USERNAME = username;
73-
SpringSecurityConfiguration.SWAGGER_PASSWORD = password;
74-
69+
protected void globalConfiguration(AuthenticationManagerBuilder authentication) throws Exception {
7570
if (Stream
76-
.of(ofNullable(SWAGGER_PASSWORD), ofNullable(SWAGGER_USERNAME))
77-
.allMatch(Optional::isPresent)) {
78-
79-
authentication
80-
.inMemoryAuthentication()
81-
.passwordEncoder(ENCODER)
82-
.withUser(username)
83-
.password(ENCODER.encode(password))
84-
.authorities(List.of());
71+
.of(SWAGGER_PASSWORD, SWAGGER_USERNAME)
72+
.allMatch(Strings::notNullOrBlank)) {
73+
74+
authentication
75+
.inMemoryAuthentication()
76+
.passwordEncoder(ENCODER)
77+
.withUser(SWAGGER_USERNAME)
78+
.password(ENCODER.encode(SWAGGER_PASSWORD))
79+
.authorities(List.of());
8580
}
8681

8782

8883
authentication
89-
.userDetailsService(sessionService)
90-
.passwordEncoder(ENCODER);
84+
.userDetailsService(sessionService)
85+
.passwordEncoder(ENCODER);
9186
}
9287

9388
@Bean
9489
public AuthenticationManager authenticationManager(
9590
AuthenticationConfiguration configuration
9691
) throws Exception {
97-
return configuration.getAuthenticationManager();
92+
return configuration.getAuthenticationManager();
9893
}
9994

10095
@Bean
10196
@Order(1)
10297
public SecurityFilterChain api(HttpSecurity http) throws Exception {
103-
PUBLICS.injectOn(http);
104-
105-
http
106-
.antMatcher("/api/**")
107-
.authorizeRequests()
108-
.anyRequest()
109-
.authenticated()
110-
.and()
111-
.csrf()
112-
.disable()
113-
.exceptionHandling()
114-
.authenticationEntryPoint((request, response, exception) -> forbidden(response))
115-
.and()
116-
.sessionManagement()
117-
.sessionCreationPolicy(STATELESS)
118-
.and()
119-
.addFilterBefore(filter, UsernamePasswordAuthenticationFilter.class)
120-
.cors()
121-
.configurationSource(request -> new CorsConfiguration().applyPermitDefaultValues());
122-
123-
return http.build();
98+
PUBLICS.injectOn(http);
99+
100+
http
101+
.antMatcher("/api/**")
102+
.authorizeRequests()
103+
.anyRequest()
104+
.authenticated()
105+
.and()
106+
.csrf()
107+
.disable()
108+
.exceptionHandling()
109+
.authenticationEntryPoint((request, response, exception) -> forbidden(response))
110+
.and()
111+
.sessionManagement()
112+
.sessionCreationPolicy(STATELESS)
113+
.and()
114+
.addFilterBefore(filter, UsernamePasswordAuthenticationFilter.class)
115+
.cors()
116+
.configurationSource(request -> new CorsConfiguration().applyPermitDefaultValues());
117+
118+
return http.build();
124119
}
125120

126121
@Bean
127122
@Order(2)
128123
public SecurityFilterChain app(HttpSecurity http) throws Exception {
129-
http
130-
.antMatcher("/app/**")
131-
.authorizeRequests()
132-
.antMatchers(GET, LOGIN_URL, "/app", "/app/register", "/app/recovery/**")
133-
.permitAll()
134-
.antMatchers(POST, "/app/register", "/app/recovery/**")
135-
.permitAll()
136-
.anyRequest()
137-
.hasAuthority("USER")
138-
.and()
139-
.csrf()
140-
.disable()
141-
.formLogin()
142-
.loginPage(LOGIN_URL)
143-
.failureUrl(LOGIN_ERROR_URL)
144-
.defaultSuccessUrl(HOME_URL)
145-
.usernameParameter(USERNAME_PARAMETER)
146-
.passwordParameter(PASSWORD_PARAMETER)
147-
.and()
148-
.rememberMe()
149-
.key(TOKEN_SECRET)
150-
.tokenValiditySeconds(DAY_MILLISECONDS)
151-
.and()
152-
.logout()
153-
.deleteCookies(SESSION_COOKIE_NAME)
154-
.logoutRequestMatcher(new AntPathRequestMatcher(LOGOUT_URL))
155-
.logoutSuccessUrl(LOGIN_URL)
156-
.and()
157-
.exceptionHandling()
158-
.accessDeniedPage(ACESSO_NEGADO_URL);
159-
160-
return http.build();
124+
http
125+
.antMatcher("/app/**")
126+
.authorizeRequests()
127+
.antMatchers(GET, LOGIN_URL, "/app", "/app/register", "/app/recovery/**")
128+
.permitAll()
129+
.antMatchers(POST, "/app/register", "/app/recovery/**")
130+
.permitAll()
131+
.anyRequest()
132+
.hasAuthority("USER")
133+
.and()
134+
.csrf()
135+
.disable()
136+
.formLogin()
137+
.loginPage(LOGIN_URL)
138+
.failureUrl(LOGIN_ERROR_URL)
139+
.defaultSuccessUrl(HOME_URL)
140+
.usernameParameter(USERNAME_PARAMETER)
141+
.passwordParameter(PASSWORD_PARAMETER)
142+
.and()
143+
.rememberMe()
144+
.key(TOKEN_SECRET)
145+
.tokenValiditySeconds(DAY_MILLISECONDS)
146+
.and()
147+
.logout()
148+
.deleteCookies(SESSION_COOKIE_NAME)
149+
.logoutRequestMatcher(new AntPathRequestMatcher(LOGOUT_URL))
150+
.logoutSuccessUrl(LOGIN_URL)
151+
.and()
152+
.exceptionHandling()
153+
.accessDeniedPage(ACESSO_NEGADO_URL);
154+
155+
return http.build();
161156
}
162157

163158
@Bean
164159
@Order(4)
165160
public SecurityFilterChain swagger(HttpSecurity http) throws Exception {
166-
if (Stream
167-
.of(ofNullable(SWAGGER_PASSWORD), ofNullable(SWAGGER_USERNAME))
168-
.allMatch(Optional::isPresent)) {
161+
if (Stream
162+
.of(SWAGGER_PASSWORD, SWAGGER_USERNAME)
163+
.allMatch(Strings::notNullOrBlank)) {
169164

170165
http
171-
.antMatcher("/swagger-ui/**")
172-
.authorizeRequests()
173-
.anyRequest()
174-
.authenticated()
175-
.and()
176-
.sessionManagement()
177-
.sessionCreationPolicy(STATELESS)
178-
.and()
179-
.httpBasic();
166+
.antMatcher("/swagger-ui/**")
167+
.authorizeRequests()
168+
.anyRequest()
169+
.authenticated()
170+
.and()
171+
.sessionManagement()
172+
.sessionCreationPolicy(STATELESS)
173+
.and()
174+
.httpBasic();
180175
}
181176

182177
return http.build();

api/src/main/java/com/github/throyer/common/springboot/domain/session/service/SessionService.java

Lines changed: 45 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -25,64 +25,62 @@
2525
@Service
2626
public class SessionService implements UserDetailsService {
2727

28-
private final UserRepository repository;
28+
private final UserRepository repository;
2929

30-
public SessionService(UserRepository repository) {
31-
this.repository = repository;
32-
}
30+
public SessionService(UserRepository repository) {
31+
this.repository = repository;
32+
}
3333

34-
@Override
35-
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
36-
var user = repository.findByEmail(email)
37-
.orElseThrow(() -> new UsernameNotFoundException(message(INVALID_USERNAME)));
38-
39-
return new Authorized(user);
40-
}
34+
@Override
35+
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
36+
var user = repository.findByEmail(email)
37+
.orElseThrow(() -> new UsernameNotFoundException(message(INVALID_USERNAME)));
4138

42-
public static void authorize(
43-
HttpServletRequest request,
44-
HttpServletResponse response
45-
) {
46-
if (PUBLICS.anyMatch(request)) {
47-
return;
48-
}
39+
return new Authorized(user);
40+
}
4941

50-
var token = Authorization.extract(request);
42+
public static void authorize(
43+
HttpServletRequest request,
44+
HttpServletResponse response) {
45+
if (PUBLICS.anyMatch(request)) {
46+
return;
47+
}
5148

52-
if (isNull(token)) {
53-
return;
54-
}
49+
var token = Authorization.extract(request);
5550

56-
try {
57-
var authorized = JWT.decode(token, TOKEN_SECRET);
58-
SecurityContextHolder
59-
.getContext()
60-
.setAuthentication(authorized.getAuthentication());
61-
} catch (Exception exception) {
62-
expired(response);
63-
}
51+
if (isNull(token)) {
52+
return;
6453
}
6554

66-
public static Optional<Authorized> authorized() {
67-
try {
68-
var principal = getPrincipal();
55+
try {
56+
var authorized = JWT.decode(token, TOKEN_SECRET);
57+
SecurityContextHolder
58+
.getContext()
59+
.setAuthentication(authorized.getAuthentication());
60+
} catch (Exception exception) {
61+
expired(response);
62+
}
63+
}
6964

70-
if (nonNull(principal) && principal instanceof Authorized authorized) {
71-
return of(authorized);
72-
}
73-
return empty();
74-
} catch (Exception exception) {
75-
return empty();
76-
}
65+
public static Optional<Authorized> authorized() {
66+
try {
67+
var principal = getPrincipal();
7768

69+
if (nonNull(principal) && principal instanceof Authorized authorized) {
70+
return of(authorized);
71+
}
72+
return empty();
73+
} catch (Exception exception) {
74+
return empty();
7875
}
76+
}
7977

80-
private static Object getPrincipal() {
81-
var authentication = SecurityContextHolder.getContext()
82-
.getAuthentication();
83-
if (nonNull(authentication)) {
84-
return authentication.getPrincipal();
85-
}
86-
return null;
78+
private static Object getPrincipal() {
79+
var authentication = SecurityContextHolder.getContext()
80+
.getAuthentication();
81+
if (nonNull(authentication)) {
82+
return authentication.getPrincipal();
8783
}
84+
return null;
85+
}
8886
}

0 commit comments

Comments
 (0)