인증(Authentication)
- 인증을 통해 사용자를 식별
인가(Authorization)
- 인가를 통해 시스템 자원에 대한 접근을 통제
Ex) 사원증 ( 입구에서는 모두 사원증을 통해 입장(인증)-> 사무실, 제한된 구역에 따른 입장 할 수 있는 권한(인가)를 통해 관리
개인적으로 전에 적용했던 부분은 -> 세션을 통한 로그인 (HttpSession)
1. 세션을 체크
2. 로그인 성공 -> 관리자 권한만 게시글 삭제
3. 문제점 - 유지보수 과정중에 인증/인가 관련된 코드를 모든 클래스 메소드 마다 적용하면 유지보수가 어렵다.
- 모든 사이트 내에 아무런 제약과 조건 없이 모두 접근이 가능해진다.
4. 해결점 - HttpSession을 통한 인증/인가 방법은 코드를 모든 클래스 메소드마다 적용하여 유지보수가 어려워진다.
따라서, 스프링 시큐리티를 적용한다.
[ Springboot Security dependency 추가 ]
<!-- security config 설정 -->
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-config -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>5.1.7.RELEASE</version>
</dependency>
[ Springboot Security dependency 추가 된 후 자동으로 재시작 되면 아래와 같은 화면이 출력된다.]
mvnrepository 사이트에서 추가
참조사이트 :
https://mvnrepository.com/artifact/org.springframework.security/spring-security-config/5.1.7.RELEASE
기본 아이디 : user
기본 비밀번호 : 위의 출력된 password를 입력하면 접근이 제한된 페이지로 접근이 가능하다.
별다른 설정 없이 기본적으로 Security를 적용하고 나면 아이디/패스워드를 통해서 제한 된 페이지를 제공한다.
SecurityConfig 클래스를 생성해서 WebSecurityConfigurerAdapter 클래스에서 configure()메소드를 통해서 시큐리티를 다양하게 재정의 해서 사용이 가능하다(커스터마이징 가능)
package com.rubypaper.config;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
@Override
protected void configure(HttpSecurity security) throws Exception{
}
}
configure() 메소드를 통해서 재정의 하여 커스터마이징이 가능하다.
위의 클래스 소스로 설정이 되면 강제적으로 로그인 해야 했던 부분이 사라진다.
package com.rubypaper.config;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
@Override
protected void configure(HttpSecurity security) throws Exception{
security.authorizeRequests().antMatchers("/").permitAll();
security.authorizeRequests().antMatchers("/member/**").authenticated();
security.authorizeRequests().antMatchers("/manager/**").hasRole("MANAGER");
security.authorizeRequests().antMatchers("/admin/**").hasRole("ADMIN");
security.csrf().disable();
//form태그기반의 로그인을 지원하는 설정
security.formLogin();
}
}
스프링부트에서 제공하는 로그인 페이지 말고 사용자가 직접 만든 로그인 페이지를 연결하고 싶은 경우
security.formLogin().loginPage("/login").defaultSuccessUrl("/loginSuccess",true);
위의 소스 처럼 사용하면 된다.
loginPage() 메소드 역할 -> 로그인에 사용할 화면을 지정
defaultSuccessUrl() 메소드 역할 -> 로그인 성공한 경우 이동할 URL 작성
메모리를 통한 사용자 인증 방법 소스는 아래와 같다.
package com.rubypaper.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
@Override
protected void configure(HttpSecurity security) throws Exception{
security.authorizeRequests().antMatchers("/").permitAll();
security.authorizeRequests().antMatchers("/member/**").authenticated();
security.authorizeRequests().antMatchers("/manager/**").hasRole("MANAGER");
security.authorizeRequests().antMatchers("/admin/**").hasRole("ADMIN");
security.csrf().disable();
//form태그기반의 로그인을 지원하는 설정
// security.formLogin();
security.formLogin().loginPage("/login").defaultSuccessUrl("/loginSuccess",true);
}
//메모리를 통한 사용자 인증
@Autowired
public void authenticate(AuthenticationManagerBuilder auth) throws Exception{
auth.inMemoryAuthentication()
.withUser("manager")
.password("{noop}manager123")
.roles("MANAGER");
auth.inMemoryAuthentication()
.withUser("admin")
.password("{noop}admin123")
.roles("ADMIN");
}
}
마지막 정리
package com.rubypaper.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
@Override
protected void configure(HttpSecurity security) throws Exception{
security.authorizeRequests().antMatchers("/").permitAll();
security.authorizeRequests().antMatchers("/member/**").authenticated();
security.authorizeRequests().antMatchers("/manager/**").hasRole("MANAGER");
security.authorizeRequests().antMatchers("/admin/**").hasRole("ADMIN");
security.csrf().disable();
//form태그기반의 로그인을 지원하는 설정
// security.formLogin();
security.formLogin().loginPage("/login").defaultSuccessUrl("/loginSuccess",true);
//Security - 권한이 없어서 해당 페이지를 볼수 없을 경우 페이지 이동할 떄 사용
//인증되지 않은 사용자에게 제공할 URL을 사용 - accessDeniedPage()을 통해서 사용
security.exceptionHandling().accessDeniedPage("/accessDenied");
//로그아웃 강제 관련 설정
//쿠기 정보 삭제- deleteCookies() 메소드를 뒤에 추가로 사용
//logoutSuccessUrl("/login") 로그아웃 후에 이동할 화면 설정 가능
security.logout().invalidateHttpSession(true).logoutSuccessUrl("/login");
}
//메모리를 통한 사용자 인증
@Autowired
public void authenticate(AuthenticationManagerBuilder auth) throws Exception{
auth.inMemoryAuthentication()
.withUser("manager")
.password("{noop}manager123")
.roles("MANAGER");
auth.inMemoryAuthentication()
.withUser("admin")
.password("{noop}admin123")
.roles("ADMIN");
}
}
{noop}의미
- 암호에 NoOpPasswordEncoder를 사용하겠다는 의미로 접두사 {noop} 를 붙인다.
- 참조 사이트 : https://thecodinglog.github.io/spring/security/2018/06/07/spring-security-3.html
'Spring' 카테고리의 다른 글
스프링 특징 (0) | 2020.02.03 |
---|---|
Spring Security 관련 참고사항 (0) | 2019.11.22 |
Springboot Thymeleaf 적용방법 (0) | 2019.11.18 |
Springboot JPA 쿼리메소드 사용하기 (0) | 2019.11.17 |
springboot JPA Annotation 정리 (0) | 2019.11.16 |