티스토리 뷰

728x90

1. 바로 전 포스팅 시작 페이지(Landing page) 사용하기에서 설정한 내용을 가지고 설명한다.

 

package pe.pilseong.springsecurity.config;

import org.springframework.context.annotation.Configuration;
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;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.User.UserBuilder;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
  
  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    UserBuilder users = User.withDefaultPasswordEncoder();
    
    auth.inMemoryAuthentication()
      .withUser(users.username("pilseong").password("pilseong").roles("EMPLOYEE"))
      .withUser(users.username("suel").password("suel").roles("EMPLOYEE", "MANAGER"))
      .withUser(users.username("noel").password("noel").roles("EMPLOYEE", "ADMIN"));
  }
  
  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http
      .authorizeRequests()
        .antMatchers("/").permitAll()
        .antMatchers("/employees").hasRole("EMPLOYEE")
        .antMatchers("/leaders/**").hasRole("MANAGER")
        .antMatchers("/systems/**").hasRole("ADMIN")
        .antMatchers("/test").hasAnyRole("ADMIN","MANAGER")
      .and()
      .formLogin()
        .loginPage("/showLoginPage")
        .loginProcessingUrl("/authenticateUser")
        .permitAll()
      .and()
      .logout()
        .logoutSuccessUrl("/")
        .permitAll();    
  }
}

 

2. 위의 소스에 2가지 중요한 요소가 있다.

  2-1 User Role부여

    2-1-1  각 유저와 role을 부여하는 코드인데 직관적으로 이해가능하다.

    2-1-2  한 유저에 여러 role을 지정할 수 있다.

 

    auth.inMemoryAuthentication()
      .withUser(users.username("pilseong").password("pilseong").roles("EMPLOYEE"))
      .withUser(users.username("suel").password("suel").roles("EMPLOYEE", "MANAGER"))
      .withUser(users.username("noel").password("noel").roles("EMPLOYEE", "ADMIN"));

 

  2-2 페이지 접근 설정

    2-2-1 각 페이지에 대해서 Role기준으로 접근 제어를 하고 있다.

    2-2-2 /employees는 해당 링크에 대해서 EMPLOYEE 권한을 요구한다.

    2-2-3 /leaders/**의 경우 /leaders/로 시작하는 모든 페이지 접근시 MANAGER 권한을 요구한다.

    2-2-4 hasRole은 하나의 권한만 지정하고 hasAnyRole()은 하나 이상의 권한 중 하나만 요구한다.

    2-2-5 /test 접근시 ADMIN이나 MANAGER 둘 중 하나의 권한이 있으면 접근할 수 있다.

    http
      .authorizeRequests()
        .antMatchers("/").permitAll()
        .antMatchers("/employees").hasRole("EMPLOYEE")
        .antMatchers("/leaders/**").hasRole("MANAGER")
        .antMatchers("/systems/**").hasRole("ADMIN")
        .antMatchers("/test").hasAnyRole("ADMIN","MANAGER")
      .and()
      .formLogin()
        .loginPage("/showLoginPage")
        .loginProcessingUrl("/authenticateUser")
        .permitAll()
      .and()
      .logout()
        .logoutSuccessUrl("/")
        .permitAll();    

 

    2-2-6 '/' request는 landing page를 보여주고 모든 사용자에게 접근가능하다.

    2-2-7 loginPage 이동는 context root /showLoginPage request로 가능하고

      2-2-7-1 login되지 않은 상태로 권한이 필요한 페이지 접근 시에도 login 페이지도 이동한다.

 

    2-2-8 login 요청은 context root /authenticateUser POST request로 가능하다.

    2-2-9 두 개의 Controller 클래스 소스다.

 

package pe.pilseong.springsecurity.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class LoginController {
  @GetMapping("/showLoginPage")
  public String showLoginPage() {
    return "plain-login";
  }
}


package pe.pilseong.springsecurity.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class HomeController {

  @GetMapping("/")
  public String landing() {
    return "landing";
  }
  
  @GetMapping("/employees")
  public String home() {
    return "home";
  }
  
  @GetMapping("/leaders")
  public String leaders() {
    return "leaders";
  }
  
  @GetMapping("/systems")
  public String admin() {
    return "system";
  }
}

 

  2-3 로그인 성공 후 페이지 home.jsp이다.

    2-3-1 여기에 보면 두 개의 링크가 있는데 하나는 MANAGER권한이 필요한 /leaders이고

    2-3-2 두번 째는 ADMIN 권한이 필요한 /systems으로 url을 요청한다.

    2-3-3 이 페이지는 security jsp taglib를 사용하고 있고 principal객체로 사용자 정보에 접근할 수 있다.

 

<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet"
  href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
  integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
  crossorigin="anonymous">
<title>Spring Security Custom Login Form</title>
</head>
<body>
  <div class="container">
    <h2>Company Website</h2>
    <hr>
    <p>You are now logged in</p>
    <p>
      User :: <security:authentication property="principal.username"/>
    </p>
    <p>
      Roles(s) :: <security:authentication property="principal.authorities"/>
    </p>
    <hr>
    <p>
      <a href="${ pageContext.request.contextPath }/leaders">Leadership Meeting(Only for Managers)</a>
    </p>
    <hr>
    <p>
      <a href="${ pageContext.request.contextPath }/systems">System Meeting(Only for Admins)</a>
    </p>
    <form:form action="${ pageContext.request.contextPath }/logout" method="POST">
      <input type="submit" class="btn btn-primary" value="Logout"/>
    </form:form>
  </div>
</body>
</html>

 

    2-3-4 화면은 아래와 같다.

 

3. 세부 페이지들 leaders.jsp, systems.jsp 페이지

  3-1 내용은 의미가 없기 대문에 최대한 간략하게 작성했다.

  3-2 landing 페이지로 돌아가는 링크가 있다.

  3-3 leader.jsp - 이 페이지는 유저 중 MANAGER 권한이 있는 suel만 접근 가능하다.

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
  <h1>Company Website</h1>
  <hr>
  <p>
    This is a page for Managers. We need a long vacation~ go managers!!!
  </p>
  <hr>
  <p>
    <a href="${ pageContext.request.contextPath }/">Back to Landing Page</a>
  </p>  
</body>
</html>

 

  3-4 systems.jsp - 이 페이지는 ADMIN권한이 있는 noel 만 접근 가능하다.

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
  <h1>Company Website</h1>
  <hr>
  <p>
    This is a page for Admins. Work sucks! Let's make a complaint!!!
  </p>
  <hr>
  <p>
    <a href="${ pageContext.request.contextPath }/">Back to Landing Page</a>
  </p>
</body>
</html>

 

  3-5. systems.jsp 결과 페이지

 

728x90
댓글