Jenkins

Spring - Security - JWT


Spring - Security - JWT๋ž€?

์›๋ž˜ ๋กœ๊ทธ์ธ ๋ฐฉ์‹์œผ๋กœ cookie ๋˜๋Š” session ๋ฐฉ์‹์„ ๋งŽ์ด ์ด์šฉํ•ด์™”๋‹ค.
ํ•˜์ง€๋งŒ ์ตœ๊ทผ๋“ค์–ด MSA๊ฐ€ ๋„์ž…๋˜๊ณ  ํ™•์žฅ์„ฑ์„ ๊ฐ€์ง€๋Š” DB ๊ตฌ์กฐ์™€ SNS ๋กœ๊ทธ์ธ(OAuth)๊ฐ€ ์ƒ๊ธฐ๋ฉด์„œ Token ๋ฐฉ์‹์ธ JWT๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค.

Dependency ์ถ”๊ฐ€


gradle ๋นŒ๋“œ ๊ธฐ์ค€

testImplementation 'org.springframework.security:spring-security-test'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'com.auth0:java-jwt:3.10.3'

๊ธฐ์กด์— Security์˜ Dependency์— JWT / implementation โ€˜com.auth0:java-jwt:3.10.3โ€™๋ฅผ ์ถ”๊ฐ€ํ•ด์ค€๋‹ค.

auth0๋ง๊ณ ๋„ jjwt๋ผ๋Š” ๋””ํŽœ๋˜์‹œ๊ฐ€ ์žˆ๋Š”๋ฐ ์ถ”ํ›„์— ํ•œ๋ฒˆ ์•Œ์•„๋ณด์ž

SecurityConfig


@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.csrf().disable();
		http.sessionManagement()
				.sessionCreationPolicy(SessionCreationPolicy.STATELESS) // session ๋ฐฉ์‹ ์‚ฌ์šฉ์•ˆํ•จ
			.and()
				.formLogin().disable() // form login ์‚ฌ์šฉ์•ˆํ•จ
				.httpBasic().disable() //
				.authorizeRequests()
				.antMatchers("URL")
				.access("hasRole('๊ถŒํ•œ') or hasRole('๊ถŒํ•œ') or hasRole('๊ถŒํ•œ')")
				.anyRequest().permitAll();
	}

	@Bean // PasswordEncoder Bean ๋“ฑ๋ก
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
}

JWT์‹œํ๋ฆฌํ‹ฐ๋ฅผ ์ ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ SecurityConfig ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

Config๋Š” WebSecurityConfigurerAdapter์„ ์ƒ์†๋ฐ›์•„ ์‚ฌ์šฉํ•˜๋ฉฐ @Configuration ์–ด๋…ธํ…Œ์ด์…˜์„ ์ถ”๊ฐ€ํ•œ๋‹ค.

์œ„์™€ ๊ฐ™์ด ์„ค์ •ํ›„ ํ”„๋กœ์ ํŠธ์— ์ ‘์†ํ•˜๊ฒŒ ๋˜๋ฉด ๊ธฐ๋ณธ์ ์œผ๋กœ ์‹œํ๋ฆฌํ‹ฐ์—์„œ ์ œ๊ณตํ•˜๋Š” ๋กœ๊ทธ์ธ ํ™”๋ฉด์œผ๋กœ ์ด๋™ํ•˜๊ฒŒ๋œ๋‹ค.
ํ•˜์ง€๋งŒ ํ† ํฐ๋ฐฉ์‹์„ ์ด์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— @EnableWebSecurity ์–ด๋…ธํ…Œ์ด์…˜์„ ์ถ”๊ฐ€ํ•œ๋‹ค.

SecurityFilter


Session๋ฐฉ์‹์˜ Security๋Š” Login์‹œ โ€œ/loginโ€ Url์„ ํ†ตํ•ด UsernamePasswordAuthenticationFilter๊ฐ€ ๋™์ž‘ํ•˜์—ฌ ๋กœ๊ทธ์ธ์„ ์ง„ํ–‰ํ•˜๊ฒŒ๋œ๋‹ค.

ํ•˜์ง€๋งŒ Token ๋ฐฉ์‹์€ ๋”ฐ๋กœ form์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ธฐ์— UsernamePasswordAuthenticationFilter๋ฅผ ์ง์ ‘ ๊ตฌํ˜„ํ•˜์—ฌ ๋กœ๊ทธ์ธ์„ ์ง„ํ–‰ํ•œ๋‹ค.

JwtAuthenticationFilter

// ์Šคํ”„๋ง ์‹œํ๋ฆฌ์—์„œ UsernamePasswordAuthenticationFilter ๊ฐ€ ์žˆ๋‹ค.
// /login ์š”์ฒญํ•ด์„œ username, password ์ „์†กํ•˜๋ฉด (post)
// UsernamePasswordAuthenticationFilter ๋™์ž‘์„ ํ•œ๋‹ค.
@RequiredArgsConstructor
public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

    private final AuthenticationManager authenticationManager;

    // /login ์š”์ฒญ์„ ํ•˜๋ฉด ๋กœ๊ทธ์ธ ์‹œ๋„๋ฅผ ์œ„ํ•ด์„œ ์‹คํ–‰๋˜๋Š” ํ•จ์ˆ˜
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {

        System.out.println("JwtAuthenticationFilter : ๋กœ๊ทธ์ธ ์‹œ๋„์ค‘");

        try {
			// ๋„˜์–ด์˜ค๋Š” username๊ณผ password๋Š” JSON์œผ๋กœ ๋„˜์–ด์™€ ๋”ฐ๋กœ parse์„ ํ†ตํ•ด User Object๋กœ ๋งŒ๋“ค์–ด์ค€๋‹ค.
            ObjectMapper om = new ObjectMapper();
            User user = om.readValue(request.getInputStream(), User.class);

            // 1. username, password ๋ฐ›๋Š”๋‹ค.
            UsernamePasswordAuthenticationToken authenticationToken =
                    new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword());


            // 2. ์ •์ƒ์ธ์ง€ ๋กœ๊ทธ์ธ ์‹œ๋„๋ฅผ ํ•ด๋ณธ๋‹ค. authenticationManager๋กœ ๋กœ๊ทธ์ธ ์‹œ๋„๋ฅผ ํ•˜๋ฉด
            // PrincopalDetailService์˜ loadUserByUsername() ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋œ ํ›„ ์ •์ƒ์ด๋ฉด authentication์ด ๋ฆฌํ„ด๋œ๋‹ค.
            Authentication authentication = authenticationManager.authenticate(authenticationToken);

            // 3. PrincipalDetail์„ ์„ธ์…˜์— ๋‹ด๋Š”๋‹ค. (๊ถŒํ•œ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•ด์„œ Session์ด ํ•„์š”)
            PrincipalDetails principalDetails = (PrincipalDetails) authentication.getPrincipal();
            System.out.println("๋กœ๊ทธ์ธ ์™„๋ฃŒ๋จ : " + principalDetails.getUser().getUsername());// ๋กœ๊ทธ์ธ ์ •์ƒ์ ์œผ๋กœ ๋˜์—ˆ๋‹ค๋Š” ๋œป.
            // authentication ๊ฐ์ฒด๊ฐ€ session์˜์—ญ์— ์ €์žฅ์„ ํ•ด์•ผํ•˜๊ณ  ๊ทธ ๋ฐฉ๋ฒ•์ด return ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.
            // ๋ฆฌํ„ด์˜ ์ด์œ ๋Š” ๊ถŒํ•œ ๊ด€๋ฆฌ๋ฅผ security๊ฐ€ ๋Œ€์‹  ํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ํŽธ๋ฆฌํ•˜๊ฒŒ ๊ตฌํ˜„์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
            // ๊ตณ์ด JWT ํ† ํฐ์„ ์‚ฌ์šฉํ•˜๋ฉด์„œ ์„ธ์…˜์„ ๋งŒ๋“ค ์ด์œ ๊ฐ€ ์—†๋‹ค.

            // 4. JWTํ† ํฐ์„ ๋งŒ๋“ค์–ด์„œ ์‘๋‹ตํ•ด์ค€๋‹ค.
            return authentication;
        }catch (IOException e){
            e.printStackTrace();
        }

        return null;
    }

    // attempAuthentication์‹คํ–‰ ํ›„ ์ธ์ฆ์ด ์ •์ƒ์ ์œผ๋กœ ๋˜์—ˆ์œผ๋ฉด successfulAuthentication ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋œ๋‹ค.
    // JWT ํ† ํฐ์„ ๋งŒ๋“ค์–ด์„œ request์š”์ฒญํ•œ ์‚ฌ์šฉ์ž์—๊ฒŒ JWTํ† ํฐ์„ responeํ•ด์ฃผ๋ฉด ๋œ๋‹ค.
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {

        System.out.println("successfulAuthentication ์‹คํ–‰๋จ : ์ธ์ฆ์ด ์™„๋ฃŒ๋˜์—ˆ๋‹ค๋Š” ๋œป");
        PrincipalDetails principalDetails = (PrincipalDetails) authResult.getPrincipal();

        // RSA๋ฐฉ์‹์ด ์•„๋‹Œ Hash์•”ํ˜ธ๋ฐฉ์‹
        String jwtToken = JWT.create()
                .withSubject("Subject") 											// Subject
                .withExpiresAt(new Date(System.currentTimeMillis()+(60000*10))) 	// ์œ ํšจ๊ธฐ๊ฐ„
                .withClaim("id", principalDetails.getUser().getId())				// Cliam
                .withClaim("username", principalDetails.getUser().getUsername())	// Cliam
                .sign(Algorithm.HMAC512("sign"));									// ์„œ๋ช…

        response.addHeader("Authorization", "Bearer "+jwtToken);
    }
}

์•„๋ž˜์˜ ํ•„ํ„ฐ๋ฅผ ํ†ตํ•ด ํ† ํฐ์˜ ์„œ๋ช…์ธ์ฆ๊ณผ ์œ ํšจ์„ฑ ์ฒดํฌ๋ฅผ ํ•˜๊ฒŒ๋œ๋‹ค.

JwtAuthorizationFilter

// ์‹œํ๋ฆฌํ‹ฐ๊ฐ€ filter๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”๋ฐ ๊ทธ ํ•„ํ„ฐ์ค‘์— BasicAuthenticationFilter๋ผ๋Š” ๊ฒƒ์ด ์žˆ๋‹ค.
// ๊ถŒํ•œ์ด๋‚˜ ์ธ์ฆ์ด ํ•„์š”ํ•œ ํŠน์ • ์ฃผ์†Œ๋ฅผ ์š”์ฒญํ–ˆ์„ ๋•Œ ์œ„ ํ•„ํ„ฐ๋ฅผ ๋ฌด์กฐ๊ฑด ํƒ€๊ฒŒ ๋˜์–ด์žˆ๋‹ค.
// ๋งŒ์•ฝ์— ๊ถŒํ•œ์ด ์ธ์ฆ์ด ํ•„์š”ํ•œ ์ฃผ์†Œ๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด ์ด ํ•„ํ„ฐ๋ฅผ ์•ˆํƒ„๋‹ค.
public class JwtAuthorizationFilter extends BasicAuthenticationFilter {

    private UserRepository userRepository;

    public JwtAuthorizationFilter(AuthenticationManager authenticationManager, UserRepository userRepository) {
        super(authenticationManager);
        this.userRepository = userRepository;
    }

    // ์ธ์ฆ์ด๋‚˜ ๊ถŒํ•œ์ด ํ•„์š”ํ•œ ์ฃผ์†Œ์š”์ฒญ์ด ์žˆ์„ ๋•Œ ํ•ด๋‹น ํ•„ํ„ฐ๋ฅผ ํƒ€๊ฒŒ ๋จ.
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        //super.doFilterInternal(request, response, chain); // ์‘๋‹ต ์˜ค๋ฅ˜
        System.out.println("์ธ์ฆ์ด๋‚˜ ๊ถŒํ•œ์ด ํ•„์š”ํ•œ ์ฃผ์†Œ ์š”์ฒญ์ด ๋จ.");

        String jwtHeader = request.getHeader("Authorization");
        System.out.println("jwtHeader = " + jwtHeader);

        // header๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธ
        if(jwtHeader == null || !jwtHeader.startsWith("Bearer ")){
            chain.doFilter(request, response);
            return;
        }

        // JWT ํ† ํฐ์„ ๊ฒ€์ฆ์„ ํ•ด์„œ ์ •์ƒ์ ์ธ ์‚ฌ์šฉ์ž์ธ์ง€ ํ™•์ธ
        String token = jwtHeader.replace("Bearer ", "").trim();

        String username = JWT.require(Algorithm.HMAC512("cos")).build().verify(token).getClaim("username").asString();

        System.out.println("username = " + username);

        // ์„œ๋ช…์ด ์ •์ƒ์ ์œผ๋กœ ๋จ
        if(username != null && !username.equals("")){

            System.out.println("username ์ •์ƒ");
            User findUser = userRepository.findByUsername(username);

            System.out.println("findUser = " + findUser.getUsername());
            PrincipalDetails principalDetails = new PrincipalDetails(findUser);

            // JWT ํ† ํฐ ์„œ๋ช…์„ ํ†ตํ•ด์„œ ์„œ๋ช…์ด ์ •์ƒ์ด๋ฉด Authentication ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด์ค€๋‹ค.
            Authentication authentication = new UsernamePasswordAuthenticationToken(principalDetails, null, principalDetails.getAuthorities());

            // ๊ฐ•์ œ๋กœ ์‹œํ๋ฆฌํ‹ฐ์˜ ์„ธ์…˜์— ์ ‘๊ทผํ•˜์—ฌ Authentication ๊ฐ์ฒด๋ฅผ ์ €์žฅ.
            SecurityContextHolder.getContext().setAuthentication(authentication);

        }

        chain.doFilter(request, response);
    }

}

์ด๋ ‡๊ฒŒ ์ž‘์„ฑํ•œ ํ•„ํ„ฐ๋ฅผ SecurityConfig์— ์ ์šฉํ•œ๋‹ค.


private final CorsFilter corsFilter;
private final UserRepository userRepository;

@Override
protected void configure(HttpSecurity http) throws Exception {
	//security์— filter๋“ฑ๋ก, SecurityContextPersistenceFilter ์ „์— ์‹คํ–‰ (Spring์˜ ํ•„ํ„ฐ์ข…๋ฅ˜๋ฅผ ์•Œ์•„์•ผํ•œ๋‹ค)
	//security์˜ ํ•„ํ„ฐ๋Š” CustomFilter๋ณด๋‹ค ๋ฌด์กฐ๊ฑด์ ์œผ๋กœ ์šฐ์„ ์‹คํ–‰๋œ๋‹ค.
	//http.addFilterBefore(new CustomFilter(), SecurityContextPersistenceFilter.class);
	http.csrf().disable()
			.addFilter(corsFilter) // ๋ชจ๋“  ์š”์ฒญ์€ filter๋ฅผ ๊ฑฐ์น˜๊ฒŒ๋œ๋‹ค. Controller์— @CrossOrigin(์ธ์ฆX), ์‹œํ๋ฆฌํ‹ฐ ํ•‰ํ„ฐ์— ๋“ฑ๋ก ์ธ์ฆ(O)
			.sessionManagement()
			.sessionCreationPolicy(SessionCreationPolicy.STATELESS) // session ๋ฐฉ์‹ ์‚ฌ์šฉ์•ˆํ•จ
		.and()
			.formLogin().disable() // form login ์‚ฌ์šฉ์•ˆํ•จ
			.httpBasic().disable()
			.addFilter(new JwtAuthenticationFilter(authenticationManager()))				// ๋กœ๊ทธ์ธ
			.addFilter(new JwtAuthorizationFilter(authenticationManager(), userRepository)) // ํ† ํฐ ์„œ๋ช…์ธ์ฆ
			.authorizeRequests()
			.antMatchers("/api/v1/user/**")
				.access("hasRole('ROLE_USER') or hasRole('ROLE_MANAGER') or hasRole('ROLE_ADMIN')")
			.antMatchers("/api/v1/manager/**")
				.access("hasRole('ROLE_MANAGER') or hasRole('ROLE_ADMIN')")
			.antMatchers("/api/v1/admin/**")
				.access("hasRole('ROLE_ADMIN')")
			.anyRequest().permitAll();
}

CorsConfig


Token ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜๋ฉฐ Controller ํ†ต์‹ ์ด์•„๋‹Œ RestController ํ†ต์‹ ์„ ์ž์ฃผ ์ด์šฉํ•˜๊ฒŒ ๋œ๋‹ค.

JWT๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ๋œ๋ฉด React์™€ ๊ฐ™์€ ํ”„๋กœ์ ํŠธ์™€ ํ†ต์‹ ํ•˜๋Š” ํ”„๋กœ์ ํŠธ๋ฅผ ์ง„ํ–‰ํ•˜๊ฒŒ ๋˜๋Š”๋ฐ ์ด๋•Œ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ๊ฐ€ Cors๋ฌธ์ œ์ด๋‹ค.

Cors๋ž€?

Cross Origin Resource Sharing ์˜ ์•ฝ์ž๋กœ ๋„๋ฉ”์ธ์ด ๋‹ค๋ฅธ ์ž์›์— ๋ฆฌ์†Œ์Šค๋ฅผ ์š”์ฒญํ•  ๋•Œ ์ ‘๊ทผ ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•˜๋Š” ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด๋‹ค.

Spring Project๋Š” 8080 port๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  React๋Š” 3000 port๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ๋œ๋‹ค.

๋งŒ์•ฝ React์—์„œ Spring API๋ฅผ ํ˜ธ์ถœํ•˜๊ฒŒ๋œ๋‹ค๋ฉด CORS๋ฌธ์ œ๋ฅผ ๋งŒ๋‚  ์ˆ˜ ์žˆ์„๊ฒƒ์ด๋‹ค.

์ด๊ฒƒ์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด CorsConfig๋ฅผ ์ž‘์„ฑํ•ด์ค€๋‹ค.

@Configuration
public class CorsConfig {

    @Bean
    public CorsFilter corsFilter(){
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true); // ๋‚ด ์„œ๋ฒ„๊ฐ€ ์‘๋‹ต์„ ํ•  ๋•Œ json์„ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ• ์ง€๋ฅผ ์„ค์ •ํ•˜๋Š” ๊ฒƒ
        config.addAllowedOrigin("*");     // ๋ชจ๋“  ip์— ์‘๋‹ต์„ ํ˜€์šฉํ•˜๊ฒ ๋‹ค.
        config.addAllowedHeader("*");     // ๋ชจ๋“  header์— ์‘๋‹ต์„ ํ—ˆ์šฉํ•˜๊ฒ ๋‹ค.
        config.addAllowedMethod("*");     // ๋ชจ๋“  post, get, put, delete์ ‘๊ทผ์„ ํ—ˆ์šฉํ•˜๊ฒ ๋‹ค.

        source.registerCorsConfiguration("/api/**", config);
        return  new CorsFilter(source);
    }
}

UserDetail


์‹œํ๋ฆฌํ‹ฐ๋Š” Authentication ๊ฐ์ฒด๋ฅผ ์„ธ์…˜์— ๋„ฃ๊ฒŒ๋˜๋Š”๋ฐ ์ด๊ฒƒ์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด์„œ UserDetail ์„ ์ƒ์†๋ฐ›์•„ ์‚ฌ์šฉํ•˜๊ฒŒ๋œ๋‹ค.

User Entity

@Data
public class User {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String username;
    private String password;
    private String roles; // USER,ADMIN

    public List<String> getRoleList(){
        if(this.roles.length() > 0){
            return Arrays.asList(this.roles.split(","));
        }
        return new ArrayList<>();
    }
}

Authentication ๊ฐ์ฒด

// ๋กœ๊ทธ์ธ์„ ์ง„ํ–‰์ด ์™„๋ฃŒ๊ฐ€ ๋˜๋ฉด ์‹œํ๋ฆฌํ‹ฐ session์œผ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค (Security ContextHolder)
// ์˜ค๋ธŒ์ ํŠธ ํƒ€์ž… => Authentication ํƒ€์ž… ๊ฐ์ฒด
// Authentication ์•ˆ์— User ์ •๋ณด๊ฐ€ ์žˆ์–ด์•ผ ๋จ
public class PrincipalDetails implements UserDetails{
	
	private User user; // ์œ ์ € ๊ฐ์ฒด
	
	public PrincipalDetails(User user) {
		this.user = user;
	};
	
	// ํ•ด๋‹น User์˜ ๊ถŒํ•œ์„ ๋ฆฌํ„ดํ•˜๋Š” ๊ณณ!
	@Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        Collection<GrantedAuthority> authorities = new ArrayList<>();
        user.getRoleList().forEach(r->{
            authorities.add(() -> r);
        });
        return authorities;
    }

	@Override
	public String getPassword() {
		return user.getPassword();
	}

	@Override
	public String getUsername() {
		return user.getUsername();
	}
	
	// ๊ณ„์ • ๋งŒ๋ฃŒ
	@Override
	public boolean isAccountNonExpired() {
		return true;
	}

	// ๊ณ„์ • ์ž ๊น€
	@Override
	public boolean isAccountNonLocked() {
		return true;
	}
	
	// ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์˜ค๋ž˜ ๋˜์—ˆ๋‚˜
	@Override
	public boolean isCredentialsNonExpired() {
		return true;
	}
	
	// ๊ณ„์ • ํ™œ์„ฑํ™”
	@Override
	public boolean isEnabled() {
		
		// ์‚ฌ์ดํŠธ์—์„œ ์œ ์ €๊ฐ€ 1๋…„๋™์•ˆ ๋กœ๊ทธ์ธ์„ ์•ˆํ–ˆ๋‹ค๋ฉด!! ํœด๋จผ ๊ณ„์ •์œผ๋กœ ํ•˜๊ธฐ๋กœ ํ•จ
		// ํ˜„์žฌ์‹œ๊ฐ„ - ๋กœ๊ธด์‹œ๊ฐ„ => 1๋…„์„ ์ดˆ๊ณผํ•˜๋ฉด false
		
		return true;
	}
}

ํšŒ์›๊ฐ€์ž…


ํšŒ์›๊ฐ€์ž…์€ ๊ฐ„๋‹จํ•˜๊ฒŒ ์•”ํ˜ธํ™”๋ฅผ ์ง„ํ–‰ํ•˜์—ฌ ๋“ฑ๋กํ•˜๊ฒŒ๋œ๋‹ค.

@RestController
@RequiredArgsConstructor
public class RestApiController

private final PasswordEncoder passwordEncoder; // ๋น„๋ฐ€๋ฒˆํ˜ธ ์•”ํ˜ธํ™”๊ฐ€ ํ•„์—ฌํ•˜๋‹ค. ์‹œํ๋ฆฌํ‹ฐ ๋กœ๊ทธ์ธ ๋ถˆ๊ฐ€๋Šฅ

	// ํšŒ์›๊ฐ€์ž…
	@PostMapping("join")
	public String join(@RequestBody User user) {
		
		user.setPassword(passwordEncoder.encode(user.getPassword()));
		user.setRoles("ROLE_USER");
		userRepository.save(user);

		return "ํšŒ์›๊ฐ€์ž…์™„๋ฃŒ";
	}
}

๋กœ๊ทธ์ธ


UserDetailsService

// ์‹œํ๋ฆฌํ‹ฐ ์„ค์ •์—์„œ loginProcessingUrl("/login")
// /login ์š”์ฒญ์ด ์˜ค๋ฉด ์ž๋™์œผ๋กœ UserDetailsService ํƒ€์ž…์œผ๋กœ IoC๋˜์–ด ์žˆ๋Š” loadUserByUsername ํ•จ์ˆ˜ ์‹คํ–‰
@Service
@RequiredArgsConstructor
public class PrincipalDetailsService implements UserDetailsService {

	private final UserRepository userRepository;

	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		User findUser = userRepository.findByUsername(username);

		return new PrincipalDetails(findUser);
	}
}

Categories:

Updated:

Leave a comment