Back End/☠️ Java
스프링 시큐리티(Spring Security)-사용자 정의(JdbcUserDetailsManager)
James Wetzel
2024. 10. 4. 16:00
JdbcUserDetailsManager는 SQL 데이터베이스에 저장된 사용자를 관리하며 JDBC를 통해 데이터베이스에 직접 연결한다.
프로젝트 설정
application.properties
spring.application.name=demo-2
# Spring DataSource (MySQL)
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/spring?useSSL=false&characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=root
# Spring JPA
spring.jpa.database=mysql
spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect
spring.jpa.hibernate.ddl-auto=update
spring.jpa.generate-ddl=false
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
Controller
package com.example.demo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HomeController {
@GetMapping("/hello")
public String hello() {
return "hello";
}
}
UsersEntity
package com.example.demo.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
@Entity
@Table(name = "users")
public class UsersEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(length = 30, nullable = false)
private String username;
@Column
private String password;
@Column
private String enabled;
}
AuthoritiesEntity
package com.example.demo.entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
@Entity
@Table(name = "authorities")
public class AuthoritiesEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(length = 30, nullable = false)
private String username;
@Column(length = 30, nullable = false)
private String authority;
}
SpringSecurityConfig
package com.example.demo.config;
import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.JdbcUserDetailsManager;
@Configuration
public class SpringSecurityConfig {
@Bean
UserDetailsService userDetailsService(DataSource dataSource) {
String usersByUsernameQuery = " select username, password, enabled from spring.users where username = ? ";
String authsByUserQuery = " select username, authority from spring.authorities where username = ? ";
var userDetailsManager = new JdbcUserDetailsManager(dataSource);
userDetailsManager.setUsersByUsernameQuery(usersByUsernameQuery);
userDetailsManager.setAuthoritiesByUsernameQuery(authsByUserQuery);
return userDetailsManager;
}
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
CustomAuthenticationProvider customAuthenticationProvider(UserDetailsService userDetailsService, PasswordEncoder passwordEncoder) {
return new CustomAuthenticationProvider(userDetailsService, passwordEncoder);
}
}
CustomerAuthenticationProvider
package com.example.demo.config;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
private final UserDetailsService userDetailsService;
private final PasswordEncoder passwordEncoder;
public CustomAuthenticationProvider(UserDetailsService userDetailsService, PasswordEncoder passwordEncoder) {
this.userDetailsService = userDetailsService;
this.passwordEncoder = passwordEncoder;
}
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String userName = authentication.getName();
String userPassword = String.valueOf(authentication.getCredentials());
UserDetails userDetails = this.userDetailsService.loadUserByUsername(userName);
if(userPassword.equals(userDetails.getPassword())) {
return new UsernamePasswordAuthenticationToken(userName, userPassword, userDetails.getAuthorities());
} else {
throw new BadCredentialsException("Invalid username or password");
}
}
@Override
public boolean supports(Class<?> authentication) {
return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
}
}
쿼리
insert into spring.authorities(username, authority)
values ('james', '');
insert into spring.users (username, password, enabled)
values ('james', '12345', '');
호출 테스트
추가 정보
스프링 시큐리티(Spring Security)-설정과 HTTP Basic 인증
스프링 시큐리티(Spring Security)-설정과 HTTP Basic 인증
개발 환경java 21.0.4 2024-07-16 LTSJava(TM) SE Runtime Environment (build 21.0.4+8-LTS-274)Java HotSpot(TM) 64-Bit Server VM (build 21.0.4+8-LTS-274, mixed mode, sharing) STS4스프링 시큐리티(Spring Security) 설정"Spring Start
jangjeonghun.tistory.com
728x90
반응형