
스프링 시큐리티 기본 개념 및 구현
Springboot
2022.04.30.
스프링 시큐리티(Spring Security)란?
Spring Security는 Spring 기반 애플리케이션의 보안을 담당하는 스프링 하위 프레임워크다.
왜 사용하는가 ??
Spring Security를 이용하면 “인증” 과 “권한”에 대해 쉽게 나는 너무 어렵지만 코드를 작성할 수 있도록 제공되기 때문에 사용한다.
그렇다면 인증 과 권한에 대해 조금 알아보자.
인증(Authentication)
흔히 로그인 할때 거치는 본인이 맞는지 확인하는 절차이다.
권한(Role)
인증된 사용자가 자원(Resource)에 접근 가능한지 결정하는 절차를 인가(Authoriation)라고 하는데 인가 절차를 거친 후 사용자가 갖게되는 접근 가능한 권한을 의미한다.
스프링 시큐리티 시작하기
1.dependency 추가
maven
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>Gradle
implementation 'org.springframework.boot:spring-boot-starter-security'2.기본 설정
WebSecurityConfig.java
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private final UserService userService;
@Override
public void configure(WebSecurity web) throws Exception {
//해당 요청은 인증 대상에서 제외
web.ignoring().antMatchers( "/css/**", "/img/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/login", "/signUp", "/access_reject", "/resources/**").permitAll()
.antMatchers("/userAccess").hasRole("USER")
.antMatchers("/userAccess").hasRole("ADMIN")
.and()
.formLogin()
.loginPage("/login")
.loginProcessingUrl("/login_process")
.successHandler(new LoginSuccessHandler())
.and()
.cors().disable()
.csrf().disable()
}
}- @EnableWebSecurity 어노테이션을 선언함으로서 Spring Security를 활성화 시킨다.
- authorizeRequests() : HttpServletReuqest 요청 URL에 따라 접근 권한을 설정한다.
- antMatchers(“/userAccess”) : 요청 URL 경로 패턴을 지정
- permitAll() : 모든 유저에게 접근을 허용
- hasRole(“USER”) : USER라는 권한이 있다면 접근을 허용
- hasRole(“ADMIN”) : ADMIN라는 권한이 있다면 접근을 허용
- formLogin() : form Login 설정
- loginPage(“/login”) : 커스텀 로그인 페이지 경로와 로그인 경로를 설정
- loginProcessingUrl(“login_process”) : POST로 로그인 정보를 보낼 시 경로 (기본값은 /login)
- successHandler() : Spring Security에서 제공하는 FormLogin 성공시 항상 실행시키기 위함(AuthenticationFailureHandler를 구현)
- cors().disable() : Cors 설정하지않음
- csrf().disable() : Csrf 설정하지않음
3.로그인 커스텀 페이지 생성
login.jsp
<html>
<head>
<title>로그인</title>
</head>
<body>
<div class="container">
<h1>로그인</h1>
<form action="/login_process" method="post">
<div class="form-group">
<label for="id">아이디</label>
<input type="text" name="username" id="id" class="form-control" placeholder="아이디 입력해주세요">
</div>
<div class="form-group">
<label for="password">비밀번호</label>
<input type="password" class="form-control" id="password" name="password" placeholder="비밀번호 입력해주세요">
</div>
<button type="submit" class="btn btn-primary">로그인</button>
<button type="button" class="btn btn-primary" onClick="location.href='signUp'">회원가입</button>
</form>
<br/>
</div>
</body>
</html>- WebSecurityConfig.java에서 loginProcessingUrl(“login_process”) 설정했으므로 Post 방식 이용
4.UserDetailsService를 상속 받은 UserService 생성
UserService.java
public class UserService implements UserDetailsService {
@Autowired
private UserMapper mapper;
@Override
public UserVO loadUserByUsername(String username) throws UsernameNotFoundException {
UserVO userVO = userMapper.getUser(username); //DB로부터 회원정보를 가져와 회원이 존재하는지 확인
if(userVO == null) {
throw new UsernameNotFoundException("유저 정보 존재하지않음");
}
return userVO;
}
}- login_process가 실행되면서 자동으로 UserDetailsService 타입으로 Ioc 되어있는 loadUserByUsername 실행
- loadUserByUsername의 Parameter인 username는 login.jsp에 name=""값과 동일해야함.
5. AuthenticationSuccessHandler를 상속받은 LoginSuccessHandler 생성
LoginSuccessHandler.java
@Override
public class LoginSuccessHandler implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
HttpSession session = request.getSession();
session.setAttribute("name", authentication.getName());
response.sendRedirect("/user_access");
}
}- 로그인 성공시 user_access로 Redirect
6.UserController 생성
UserController.java
@Controller
public class UserController {
@Autowired
UserService userService;
@GetMapping("/user_access")
public String userAccess(Model model, Authentication authentication) {
UserVO userVO = (UserVO) authentication.getPrincipal(); //현재 로그인한 유저의 정보를 받아온다.
model.addAttribute("userInfo", userVO.getId() + "님의" + userVO.getUserName() + "님");
return "user_access";
}
}- authentication 객체에 로그인한 유저정보(DB에서 가져온) 담겨져있음
- 로그인 성공시 결국엔 user_access.jsp로 이동
7.user_access.jsp 생성
user_access.jsp
<html>
<head>
<title>main</title>
</head>
<body>
<h1>환영합니다!!!</h1>
<%
String name = (String) session.getAttribute("name");
%>
<a href="#"><%=name%>님 환영합니다!</a>
</body>
</html>- LoginSuccessHandler.java에서 Session 객체에 로그인한 유저 이름이 담겨서 보냈으므로 로그인 성공시 로그인한 이름을 보여준다.
8.결과
-로그인 화면
-로그인 성공시