Framework/Spring Framework

(23.01.06)Spring ํ”„๋ ˆ์ž„์›Œํฌ : thymeleaf๋ฅผ ์ด์šฉํ•œ ๋ณด์•ˆ ๋กœ๊ทธ์ธ - ๋กœ๊ทธ์ธ ์—๋Ÿฌ

ํ”„๋กœ๊ทธ๋ž˜๋จธ ์˜ค์›” 2023. 1. 9.

๋กœ๊ทธ์ธ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ๋„์šฐ๊ธฐ

 

pom.xml ์„ค์ •์€ (23.01.05)๊ฒŒ์‹œ๊ธ€ ์ฐธ๊ณ !

 

 

SimpleSecurityConfig.java

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
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.WebSecurityCustomizer;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
 
@Configuration
@EnableWebSecurity
public class SimpleSecurityConfig
{
   @Bean
   BCryptPasswordEncoder  passwordEncoder()
   {
      BCryptPasswordEncoder enc = new BCryptPasswordEncoder();
      System.out.println("employee->" + enc.encode("employee"));
      System.out.println("imadmin->" + enc.encode("imadmin"));
      System.out.println("guest->" + enc.encode("guest"));
       return enc;
   } 
 
    @Bean
    WebSecurityCustomizer webSecurityCustomizer() 
    {
       return (webSecurity) -> webSecurity.ignoring().antMatchers("/resources/**""/ignore2");
    }
 
    @Bean
   SecurityFilterChain filterChain(HttpSecurity http) throws Exception 
    {
      System.out.println("์ ‘๊ทผ์ œํ•œ ์„ค์ •");
      return http.authorizeHttpRequests()/* ๊ถŒํ•œ์— ๋”ฐ๋ฅธ ์ธ๊ฐ€(Authorization) */
            .antMatchers("/""/sec/""/sec/loginForm""/sec/denied""/logout").permitAll()
              .antMatchers("/sec/hello").hasAnyRole("USER""ADMIN")
               .antMatchers("/sec/getemps").hasAnyRole("USER""ADMIN")
               .antMatchers("/sec/addemp").hasAnyRole("ADMIN")
               .antMatchers("/sec/menu").hasAnyRole("USER","GUEST","ADMIN")
               .antMatchers("/sec/sample").hasAnyRole("GUEST""ADMIN")
            //.anyRequest().authenticated()  // ์œ„์˜ ์„ค์ • ์ด์™ธ์˜ ๋ชจ๋“  ์š”์ฒญ์€ ์ธ์ฆ์„ ๊ฑฐ์ณ์•ผ ํ•œ๋‹ค
               .anyRequest().permitAll()        // ์œ„์˜ ์„ค์ • ์ด์™ธ์˜ ๋ชจ๋“  ์š”์ฒญ์€ ์ธ์ฆ ์š”๊ตฌํ•˜์ง€ ์•Š์Œ
               
            .and()
            .csrf().disable()    //csrf ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์„ ๋•Œ
            //.csrf().ignoringAntMatchers("/logout") //์š”์ฒญ์‹œ 'POST' not supported ์—๋Ÿฌ ๋ฐฉ์ง€
            //.ignoringAntMatchers("/sec/loginForm")
            //.ignoringAntMatchers("/doLogin")
 
            .formLogin().loginPage("/sec/loginForm")   // ์ง€์ •๋œ ์œ„์น˜์— ๋กœ๊ทธ์ธ ํผ์ด ์ค€๋น„๋˜์–ด์•ผ ํ•จ
               .loginProcessingUrl("/doLogin")            // ์ปจํŠธ๋กค๋Ÿฌ ๋ฉ”์†Œ๋“œ ๋ถˆํ•„์š”, ํผ action๊ณผ ์ผ์น˜ํ•ด์•ผ ํ•จ
               .failureUrl("/sec/login-error")      // ๋กœ๊ทธ์ธ ์‹คํŒจ์‹œ ๋‹ค์‹œ ๋กœ๊ทธ์ธ ํผ์œผ๋กœ
               //.failureForwardUrl("/login?error=Y")  //์‹คํŒจ์‹œ ๋‹ค๋ฅธ ๊ณณ์œผ๋กœ forward
               .defaultSuccessUrl("/sec/main"true)
               .usernameParameter("userid")  // ๋กœ๊ทธ์ธ ํผ์—์„œ ์ด์šฉ์ž ID ํ•„๋“œ ์ด๋ฆ„, ๋””ํดํŠธ๋Š” username
               .passwordParameter("userpwd")  // ๋กœ๊ทธ์ธ ํผ์—์„œ ์ด์šฉ์ž ์•”ํ˜ธ ํ•„ํŠธ ์ด๋ฆ„, ๋””ํดํŠธ๋Š” password
               .permitAll()
               
               .and()   // ๋””ํดํŠธ ๋กœ๊ทธ์•„์›ƒ URL = /logout
               .logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")) //๋กœ๊ทธ์•„์›ƒ ์š”์ฒญ์‹œ URL
             .logoutSuccessUrl("/sec/loginForm?logout=T")
             .invalidateHttpSession(true
             .deleteCookies("JSESSIONID")
             .permitAll()
             
             .and()
             .exceptionHandling().accessDeniedPage("/sec/denied")
             .and().build();
    }
 
    @Autowired 
    public void configureGlobal(AuthenticationManagerBuilder authenticationMgr) throws Exception 
    {
        authenticationMgr.inMemoryAuthentication() /* ๋ฉ”๋ชจ๋ฆฌ ๊ธฐ๋ฐ˜ ์ธ์ฆ(Authentication) */
        .withUser("employee").password("$2a$10$MZ2ANCUXIj5mrAVbytojruvzrPv9B3v9CXh8qI9qP13kU8E.mq7yO")
            .authorities("ROLE_USER")
        .and()
        .withUser("imadmin").password("$2a$10$FA8kEOhdRwE7OOxnsJXx0uYQGKaS8nsHzOXuqYCFggtwOSGRCwbcK")
            .authorities("ROLE_USER""ROLE_ADMIN")
        .and()
        .withUser("guest").password("$2a$10$ABxeHaOiDbdnLaWLPZuAVuPzU3rpZ30fl3IKfNXybkOG2uZM4fCPq")
            .authorities("ROLE_GUEST");
    }
}
cs

 

 

 

 

SecurityController.java

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
31
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
 
@Controller
@RequestMapping("/sec")
public class SecurityController {
    @GetMapping("/")
 
    public String index() {
        return "thymeleaf/index";
    }
    @GetMapping("/loginForm")
 
    public String loginForm() {
        return "thymeleaf/loginForm";
    }
 
    @GetMapping("/main")
    public String goMain() {
        return "thymeleaf/main";
    }
 
    @GetMapping("/login-error")
    public String fail(Model model) {
        model.addAttribute("loginError",true);
        return "thymeleaf/loginForm";
    }
}
cs

 

 

 

index.html

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
31
32
33
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
     xmlns:sec="http://www.thymeleaf.org/extras/thymeleaf-extras-springsecurity5">
<head>
<meta charset="utf-8">
<title>INDEX</title>
</head>
<body>
<h2>Welcome</h2>
        <p>Spring Security Thymeleaf tutorial</p>
        <div sec:authorize="isAnonymous()">
           You should login in for using this.
           
        </div>
        <div sec:authorize="hasRole('USER')">
           Text visible to user.
        </div>
        <div sec:authorize="hasRole('ADMIN')">
           Text visible to admin.
        </div>
        <div sec:authorize="hasAnyRole('ADMIN','USER')">
           Text visible to admin or user.
        </div>
        <div sec:authorize="isAuthenticated()">
            <div>Authenticated username:
              <span sec:authentication="name"></span>
           </div>
           <div>Authenticated user roles:
              <span sec:authentication="principal.authorities"></span>
           </div>
        </div>
</body>
</html>
cs

 

 

 

loginForm.html

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
31
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>๋กœ๊ทธ์ธํ•ด์ฃผ์„ธ์š”</title>
<style>
    h1{width:fit-content; margin:0 auto;}
   label{display:inline-block;width:3em; text-align: right; 
      margin-right:1em; }
   input { width: 5em; }
   form {width:fit-content; padding:0.5em; margin:0 auto; 
      border:1px solid black;}
   button { margin: 5px; }
   div:last-child { text-align: center;} 
   .error {color: red; text-align: center;}
</style>
</head>
<body>
<h1>๋กœ๊ทธ์ธ</h1>
<p th:if= "${loginError}" class="error">Wrong userid or password</p>
<form action="/doLogin" method="post">
   <div><label>์•„์ด๋””</label> 
      <input id="uid" type="text" name="userid" value="">
   </div>
   <div><label>์•” ํ˜ธ</label> 
      <input id="pwd" type="password" name="userpwd" value="">
   </div>
   <div><button type="submit">๋กœ๊ทธ์ธ</button></div>
</form>
</body>
</html>
cs

 

 

 

์‹คํ–‰๊ฒฐ๊ณผ : 

 

 

 

 

 

๋Œ“๊ธ€