반응형
Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- docker
- MariaDB
- MSsql
- jenkins
- Java
- spring
- SpringBoot
- mysql
- rocky9
- PM2
- console
- NextJS
- post
- Eclipse
- submit
- mybatis
- git
- config
- security
- nodejs
- node.js
- javascript
- yona
- Next.js
- spring3
- centos7
- ajax
- Maven
- popup
- jquery
Archives
- Today
- Total
ふたりで
SpringBoot+Security ajax Unauthorized request filter 본문
728x90
반응형
SMALL
springboot에 spring security를 적용한 경우 세션이 종료된 상태일 때 기본적으로 모든 요청(request)에 대해
login페이지로 전환된다.
이럴 경우 문제는 세션이 종료된 이후 ajax요청이 오면 302(리다이렉트) 처리가 되며, ajax요청에 대한 결과는 200.OK
가 된다.
하여... ajax요청 스크립트 내에서 세션 타임아웃으로 처리를 하는 방법을 구글링 해 보았으나 음...
없는 것 같다...
검색해서 나오는 방법은 spring security설정으로 ajax요청을 구분하여 결과를 리턴하는 방법이 대부분이었다.
아래 구글링 해보고..., 테스트해 보고..., 실사용 환경에도 적용한 내용을 정리한다.
1. 환경.
- springboot2.x
- spring-security5.x
2. pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
3. AjaxAwareAuthenticationEntryPoint.java 클래스를 생성한다.
해당 클래스는 인증되지 않은 ajax요청일 때만 403으로 결과를 리턴하고, 그 외의 경우 파라미터로 명시된 url로 리다이렉트 한다.
package com.xxxxxx.xxxx.config;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
/**
* @author graykang
* 인증되지 않은 요청이 AJAX일경우는 403으로 응답 그외엔 파라메터의 url로 전환.
*/
public class AjaxAwareAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint{
public AjaxAwareAuthenticationEntryPoint(String loginUrl) {
super(loginUrl);
}
@Override
public void commence(
HttpServletRequest request,
HttpServletResponse response,
AuthenticationException authException)
throws IOException, ServletException {
String ajaxHeader = ((HttpServletRequest) request).getHeader("X-Requested-With");
boolean isAjax = "XMLHttpRequest".equals(ajaxHeader);
if (isAjax) {
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Ajax REquest Denied (Session Expired)");
} else {
super.commence(request, response, authException);
}
}
}
4. WebSecurityConfig.java 에 AjaxAwareAuthenticationEntryPoint설정.
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
@Autowired
UserDetailsService CustomUserDetailServiceImpl;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(CustomUserDetailServiceImpl).passwordEncoder(mysqlPasswordEncoder());
}
/**로그인성공 후처리
* @return
*/
private SuccessHandlerImpl successHandler() {
return new SuccessHandlerImpl();
}
/**로그인실패 후처리
* @return
*/
private AuthFailHandlerImpl authFailHandler() {
return new AuthFailHandlerImpl();
}
/**인증되지 않은 요청중 AJAX요청일 경우 403으로 응답, AJAX요청이 아닐 경우 login으로 리다이렉트
* @param url
* @return
*/
private AjaxAwareAuthenticationEntryPoint ajaxAwareAuthenticationEntryPoint(String url) {
return new AjaxAwareAuthenticationEntryPoint(url);
}
@Override
public void configure(WebSecurity web) throws Exception
{
// static 디렉터리의 하위 파일 목록은 인증 무시 ( = 항상통과 )
web.ignoring().antMatchers("/common/**","/lib/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers(
"/resource/**",
"/login",
"/login-error",
"/gateway/**"
).permitAll() /*인증이 필요없는 정적 데이터*/
.antMatchers("/user/**").hasRole("USER")
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/mgr/**").hasRole("MGR")
.anyRequest().authenticated() /* 그 외 모든 요청은 인증된 사용자만 접근이 가능하게 처리*/
.and().formLogin()
.loginPage("/login")
.loginProcessingUrl("/loginPro")
.failureHandler(authFailHandler())
.successHandler(successHandler())
.permitAll()
.and().logout()
.logoutUrl("/logout") /*로그아웃 url*/
.logoutSuccessUrl("/login") /*로그아웃 성공시 연결할 url*/
.invalidateHttpSession(true)/*로그아웃시 세션 제거*/
.deleteCookies("JSESSIONID")/*쿠키제거*/
.clearAuthentication(true)/*권한정보 제거*/
.permitAll()
.and().exceptionHandling()
.authenticationEntryPoint(ajaxAwareAuthenticationEntryPoint("/login"))
.accessDeniedPage("/accessdenied");//url
http.csrf().disable();
http.headers().frameOptions().disable();
}
}
위의 내용 중 중요하게 봐야 할 부분
/**인증되지 않은 요청중 AJAX요청일 경우 403으로 응답, AJAX요청이 아닐 경우 login으로 리다이렉트
* @param url
* @return
*/
private AjaxAwareAuthenticationEntryPoint ajaxAwareAuthenticationEntryPoint(String url) {
return new AjaxAwareAuthenticationEntryPoint(url);
}
.and().exceptionHandling()
.authenticationEntryPoint(ajaxAwareAuthenticationEntryPoint("/login"))
.accessDeniedPage("/accessdenied");//url
authenticationEntryPoint에 ajaxAwareAuthenticationEntryPoint("/login")로 필터를 등록하였다.
728x90
반응형
LIST
'Spring' 카테고리의 다른 글
springboot+war(deploy error ServletInitializer(listenerStop) contextDestroyed 실패시 해결...) (0) | 2021.03.22 |
---|---|
springboot2.3.X SchedulerConfig (0) | 2020.12.21 |
springboot2+mybatis+maven 다중(멀티) datasource 설정. (0) | 2020.12.11 |
springboot @Scheduled 사용 해 보기 (0) | 2020.12.01 |
response Body에 담긴 Json 문자 파싱 (0) | 2020.12.01 |
Comments