Skip to content

Commit

Permalink
feat(auth): API 인증(Auth) 여부 확인 로직 변경 (URI 체크 -> @PreAuthorize 사용)
Browse files Browse the repository at this point in the history
- 기존 URI를 직접 체크하여 인증 여부를 확인했던 방식을 `@PreAuthorize("isAuthenticated()")` 방식으로 변경
- `@PreAuthorize`가 선언되어 있는 컨트롤러만 인증(Auth) 진행
  • Loading branch information
giibeom committed Nov 24, 2022
1 parent e4053dc commit 261b4a9
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,17 @@
import com.codesoom.assignment.common.authentication.filters.JwtAuthenticationFilter;
import com.codesoom.assignment.session.application.AuthenticationService;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.authentication.HttpStatusEntryPoint;

import javax.servlet.Filter;

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final AuthenticationService authenticationService;

Expand All @@ -26,6 +31,13 @@ protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.addFilterBefore(authenticationErrorFilter, JwtAuthenticationFilter.class)
.addFilter(authenticationFilter);
.addFilter(authenticationFilter)
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.exceptionHandling()
.authenticationEntryPoint(
new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED)
);
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package com.codesoom.assignment.common.authentication.filters;

import com.codesoom.assignment.common.authentication.security.UserAuthentication;
import com.codesoom.assignment.session.application.AuthenticationService;
import com.codesoom.assignment.session.application.exception.InvalidTokenException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.servlet.FilterChain;
Expand All @@ -26,37 +28,25 @@ public JwtAuthenticationFilter(final AuthenticationManager authenticationManager
protected void doFilterInternal(final HttpServletRequest request,
final HttpServletResponse response,
final FilterChain chain) throws IOException, ServletException {
if (isNotRequiredAuthorization(request)) {
chain.doFilter(request, response);
return;
}

validateAuthToken(request);

chain.doFilter(request, response);
}

private void validateAuthToken(final HttpServletRequest request) {
String authorization = request.getHeader(HttpHeaders.AUTHORIZATION);

if (authorization == null) {
throw new InvalidTokenException("");
if (authorization != null) {
Long userId = getUserIdByAccessToken(authorization);
setAuthentication(userId);
}

String accessToken = authorization.substring("Bearer ".length());
authenticationService.parseToken(accessToken);
chain.doFilter(request, response);
}

private boolean isNotRequiredAuthorization(final HttpServletRequest request) {
if (!request.getRequestURI().startsWith("/products")) {
return true;
}
private static void setAuthentication(Long userId) {
Authentication authentication = new UserAuthentication(userId);

if (HttpMethod.GET.toString().equals(request.getMethod())
|| HttpMethod.OPTIONS.toString().equals(request.getMethod())) {
return true;
}
SecurityContext context = SecurityContextHolder.getContext();
context.setAuthentication(authentication);
}

return false;
private Long getUserIdByAccessToken(String authorization) {
String accessToken = authorization.substring("Bearer ".length());
return authenticationService.parseToken(accessToken);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.codesoom.assignment.common.authentication.security;

import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;

import java.util.ArrayList;
import java.util.List;

public class UserAuthentication extends AbstractAuthenticationToken {
private final Long userId;

public UserAuthentication(Long userId) {
super(authorities());
this.userId = userId;
}

@Override
public Object getCredentials() {
return null;
}

@Override
public Object getPrincipal() {
return userId;
}

@Override
public boolean isAuthenticated() {
return true;
}

private static List<GrantedAuthority> authorities() {
List<GrantedAuthority> authorities = new ArrayList<>();
// TODO: userId에 따라서 다른 권한 부여
authorities.add(new SimpleGrantedAuthority("USER"));
return authorities;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@
import com.codesoom.assignment.product.presentation.dto.ProductData;
import com.codesoom.assignment.session.application.AuthenticationService;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestAttribute;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
Expand Down Expand Up @@ -50,22 +51,25 @@ public Product detail(@PathVariable final Long id) {

@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public Product create(@RequestAttribute final Long userId,
@RequestBody @Valid final ProductData productData) {
@PreAuthorize("isAuthenticated()")
public Product create(@RequestBody @Valid final ProductData productData,
final Authentication authentication) {
return productService.createProduct(productData);
}

@PatchMapping("{id}")
public Product update(@RequestAttribute final Long userId,
@PathVariable final Long id,
@RequestBody @Valid final ProductData productData) {
@PreAuthorize("isAuthenticated()")
public Product update(@PathVariable final Long id,
@RequestBody @Valid final ProductData productData,
final Authentication authentication) {
return productService.updateProduct(id, productData);
}

@DeleteMapping("{id}")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void destroy(@RequestAttribute final Long userId,
@PathVariable final Long id) {
@PreAuthorize("isAuthenticated()")
public void destroy(@PathVariable final Long id,
final Authentication authentication) {
productService.deleteProduct(id);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ class ProductControllerMockTest {

@BeforeEach
void setUp() {
given(authenticationService.parseToken(eq(VALID_TOKEN_1.토큰_값())))
.willReturn(VALID_TOKEN_1.아이디());

given(authenticationService.parseToken(eq(INVALID_VALUE_TOKEN_1.토큰_값())))
.willThrow(new InvalidTokenException(INVALID_VALUE_TOKEN_1.토큰_값()));
}
Expand Down

0 comments on commit 261b4a9

Please sign in to comment.