Framework/Spring Framework

(23.01.05)Spring ํ”„๋ ˆ์ž„์›Œํฌ: ๋กœ๊ทธ์ธ ๋ณด์•ˆ (SimpleSecurity)

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

โ—โ—Spring ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•œ ๋ณด์•ˆ๋œ ๋กœ๊ทธ์ธ ๊ธฐ๋Šฅโ—โ—

 

 

๋จผ์ € ํผ ์„ค์ •์„ ํ•ด์ค˜์•ผํ•œ๋‹ค.

 	<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
      </dependency>
      <dependency>
          <groupId>org.springframework.security</groupId>
          <artifactId>spring-security-taglibs</artifactId>
      </dependency>
      <dependency>
          <groupId>org.springframework.security</groupId>
          <artifactId>spring-security-web</artifactId>
      </dependency>
      <dependency>
          <groupId>org.springframework.security</groupId>
          <artifactId>spring-security-config</artifactId>
      </dependency>

 

pom.xml ์— dependency์— ์œ„ ์ฝ”๋“œ๋ฅผ ๋„ฃ์–ด์ค˜์•ผ ํ•œ๋‹ค.

 

 

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
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().requestMatchers("/resources/**""/ignore2");
    }
 
    @Bean
    SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        System.out.println("์ ‘๊ทผ์ œํ•œ ์„ค์ •");
        return http.authorizeHttpRequests()/* ๊ถŒํ•œ์— ๋”ฐ๋ฅธ ์ธ๊ฐ€(Authorization) */
                .requestMatchers("/""/sec""/sec/loginForm""/sec/denied""/logout").permitAll()
                .requestMatchers("/sec/hello").hasAnyRole("USER""ADMIN")
                .requestMatchers("/sec/getemps").hasAnyRole("USER""ADMIN")
                .requestMatchers("/sec/addemp").hasAnyRole("ADMIN")
                .requestMatchers("/sec/menu").hasAnyRole("USER""GUEST""ADMIN")
                .requestMatchers("/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/loginForm?error=T"// ๋กœ๊ทธ์ธ ์‹คํŒจ์‹œ ๋‹ค์‹œ ๋กœ๊ทธ์ธ ํผ์œผ๋กœ
                // .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
import org.springframework.stereotype.Controller;
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("/loginForm")
 
    public String loginForm() {
        return "thymeleaf/loginForm";
    }
 
    @GetMapping("/main")
 
    public String goMain() {
        return "thymeleaf/main";
    }
}
 
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
<!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;
</style>
</head>
<body>
<h1>๋กœ๊ทธ์ธ</h1>
<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

 

 

 

 

main.html

1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>๋ฉ”์ธํŽ˜์ด์ง€</title>
</head>
<body>
<a th:href="${'/logout'}">๋กœ๊ทธ์•„์›ƒ</a>
</body>
</html>
cs

 

 

 

 

 

 

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

 

id, pw ๋‘˜๋‹ค employee ๋„ฃ์œผ๋ฉด ๋กœ๊ทธ์ธ์ด ์„ฑ๊ณตํ•˜์—ฌ main.html๋กœ ๊ฐ€๋Š”๊ฑธ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

 

 

๋กœ๊ทธ์ธ ์‹คํŒจ์‹œ

 

 

๋กœ๊ทธ์•„์›ƒ์‹œ

๋Œ“๊ธ€