Spring Boot 에서 Security Form Login 적용 방법이다.

먼저, 간단한 DB, 의존성 세팅과 DB연결 후 Security를 적용한다.

 

1. 기본 세팅

1.1 DB설정

로그인에 사용할 DB테이블을 먼저 생성한다. 

CREATE TABLE `user` (
	`id` VARCHAR(50) NOT NULL,
	`pw` VARCHAR(255) NULL DEFAULT NULL,
	PRIMARY KEY (`id`)
)

 

1.2 dependency 설정

DB는 현재 MariaDB와 JPA를 사용하며, spring security 의존성과 함께 추가한다.

implementation 'mysql:mysql-connector-java'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-security'

 

1.3 DB 연결 설정

application.yml(properties) 파일에 DB 연결 정보를 추가 한다.

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: "jdbc:mysql://localhost:3306/test?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Seoul"
    username:
    password:
  jpa:
    hibernate:
      ddl-auto: update
    generate-ddl: false
    show-sql: true
    database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
    properties: 
      hibernate:
        format_sql: true

 

2. JPA 적용

Jpa는 Entity와 Interface로 이루어진 Repository를 생성하면 간단하게 적용할 수 있다.

2.1 Entity 생성

UserVO를 생성하여 생성한 DB테이블에 맞게 VO에 Entity와 Column명 들을 설정한다.

@Getter
@Setter
@NoArgsConstructor
@Entity
@Table(name = "user")
public class UserVO {

	@Id
	@Column(name = "id")
	private String id;
	
	@Column(name = "pw")
	private String pw;
	
	@Column(name = "name")
	private String name;
}

 

2.2 JpaRepository 생성

VO로 생성한 table을 연결할 JpaRepository를 생성한다.

public interface UserRepository extends JpaRepository<UserVO, String> {
	
}

 

3. Security 적용

3.1 WebSecurityConfigurerAdapter 적용

먼저 WebSecurityConfigurerAdapter를 상속받고, 아래 2개의 메소드를 Override하고 Bean을 등록한다.

 

1. configure(HttpSecurity http) 메소드는 기본적인 security 기본 설정을 하는 것이다. 현재는 csrf를 비활성화 시키고,

authorizeRequests()를 이용하여 요청에대한 권한을 처리한다. /login 경로는 권한이 없어도 접속을 허용하고, anyRequest().authenticated()를 통해 이 외의 경로는 권한이 있어야 접속을 허용한다.

formLogin() 을 통해 formLogin을 사용하겠다는 것이며, formLogin 페이지를 만들지 않았다면, Security에서 제공해주는 로그인페이지를 사용한다. 만약 로그인페이지가 있다면. formLogin().loginPage("로그인페이지 경로") 라는 loginPage 옵션을 추가하여 로그인페이지를 커스텀페이지로 변경할 수 있다.

formLogin에는 로그인 성공시 작동할 기능, 실패시 작동할 기능, 로그인 인증 URL 변경 등 다양한 기능들이 있다.

 

2. configure(AuthenticationManagerBuilder auth) 메소드는 인증방법을 의미하며,

Spring에서 xml로 Security 설정시 <authentication-manager> <authentication-provider>를 설정하는 것과 같다. 예를 들면 DB에서 사용자 정보를 불러와 현재 입력된 정보와 비교 후 UserDetails 을 반환하여 인증하겠다 라는 의미이다.
현재는 CustomUserDetailSerivce 객체에 인증 방법이 있으며, 패스워드 인코더를 설정해 두었다.

 

3. PasswordEncoder는 로그인시 DB에 BCrpyt로 저장되어있는 패스워드를 로그인할 때 입력한 비밀번호와 비교하기 위해 사용되며, 이는 인증할 때 사용되는 configure(AuthenticationManagerBuilder auth) 메소드에 사용될 것이다.

 

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

	@Autowired
	private CustomUserDetailService userDetailsService;
	
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		// TODO Auto-generated method stub
		http
			.csrf().disable()
			.authorizeRequests()
				.antMatchers("/login").permitAll()
				.anyRequest().authenticated()
			.and()
			.formLogin();
	}
	
    @Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		// TODO Auto-generated method stub
    	auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
	}

	@Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

}

 

3.2 인증을 처리할 메소드

아이디와 비밀번호를 통해 인증을 직접적으로 처리할 메소드이다.

UserDetailsService를 implements하여 loadUserByUsername을 Override한다.

권한을 임의로 생성하였으며,

2번에서 생성한 Repository를 통해 userRepository.findById(로그인아이디)를 사용하여, DB에 저장되어있는 아이디와 비밀번호를 불러온다.

불러온후 security.core에서 제공해주는 User객체를 생성하여 반환한다.

 

configure(AuthenticationManagerBuilder auth)에서 설정한 BCrpyt PasswordEncoder에는 macth라는 패스워드 비교하는 기능이 있는데 User 객체를 반환하면서 현재의 비밀번호와 폼에서 입력한 비밀번호가 match 기능으로 인하여 비밀번호를 비교해주고 비밀번호가 올바르면 로그인 인증 성공으로 처리하고 틀리다면 실패로 처리한다.

import org.springframework.security.core.userdetails.User;

@Service
public class CustomUserDetailService implements UserDetailsService {

	@Autowired
	private UserRepository userRepository;

	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		// TODO Auto-generated method stub
		
        Collection<SimpleGrantedAuthority> roles = new ArrayList<SimpleGrantedAuthority>();
		roles.add(new SimpleGrantedAuthority("ROLE_USER"));
		
        UserVO userVO =userRepository.findById(username).orElseThrow(() -> new NoSuchElementException());
		return new User(userVO.getId(), userVO.getPw(), roles);
		
	}

}

 

 

이러한 방법을 이용하여, 생성한 DB User테이블에 임의의 ID와 BCrpyt로 암호화한 패스워드를 넣고,

서버를 실행하여 /login 경로로 접속하면, Spring Security에서 기본으로 제공하는 Login Form을 이용하여 로그인을 할 수 있다.

 

오프라인 서버에 Nexus가 설치되어 있을 경우, Nexus Repository에 Maven 라이브러리들을 대량 업로드할 필요가 있다.

shell script를 이용한방법과 proxy repository를 이용한 방법이있다.

 

 

1. Shell Script를 이용한 방법.

1.1 mavenimport.sh

아래의 주소에 접속해서 Nexus 설치 서버에 mavenimport.sh를 다운받는다.

github.com/sonatype-nexus-community/nexus-repository-import-scripts

 

sonatype-nexus-community/nexus-repository-import-scripts

A few scripts for importing artifacts into Nexus Repository - sonatype-nexus-community/nexus-repository-import-scripts

github.com

 

1.2 Repository 이동

Window라면 User/.m2/repository에 있는 Maven폴더들을 Nexus가 설치되어 있는 서버에 옮긴다.

아래와 같이 mavenimport.sh와 같은 위치에 라이브러리들을 위치시킨다.

1.3 명령어 실행

넥서스 계정과 비밀번호 및 IP와 PORT 저장할 repository들을 지정하고 실행한다.

./mavenimport.sh -u ID -p PASSWORD -r http://IP:PORT/repository/maven-releases/

실행 후 Nexus 저장소를 확인하면 라이브러리들이 들어가있는 것을 확인할 수 있다.

 

2. Proxy Repository를 이용하는 방법

2.1 Local Server 또는 Online Server에 Nexus 설치

인터넷이 되는 서버에 Nexus를 먼저 설치한다.

 

 

2.2 Proxy Repository 생성

Offline으로 Nexus가 설치되어 있는 서버에 maven2 (proxy) 저장소를 생성한다.

생성하는 항목의 Remote storage 부분에 인터넷이 되는 서버의 Nexus Maven Central Repository 또는 이미 사용하고 있는 저장소의 URL을 입력한다.

 

2.3 Settings.xml 설정

Maven Settings.xml을 설정한다 Window일 경우 User/.m2/ 폴더에 있다. 만약 없으면 아래와 같이 생성한다.

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
                      http://maven.apache.org/xsd/settings-1.0.0.xsd">


</settings>

생성하였으면, 아래와 같이 <server> 와 <mirror>를 설정한다.

1. <servers>

<id>에는 <mirror>에 입력할 id 이므로 적절하게 사용한다.

<username>은 Nexus 아이디이다. Nexus에 anonymous가 허용되어있다면 입력해도 무관하다.

<password>는 Nexus 아이디의 비밀번호이다.

 

2. <mirros>

<id> 에는 위에 생성한 id를 입력한다

<name> 은 저장소의 설명이다.

<url> 에는 위에서 생성한 Offline Nexus Server의 maven2 (proxy) URL을 입력하면 된다.

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
                      http://maven.apache.org/xsd/settings-1.0.0.xsd">


 <servers>
    <server>
      <id>nexus</id>
      <username> </username>
      <password> </password>
    </server>
  
  </servers>

  <mirrors>
    <mirror>
      <id>nexus</id>
      <name>nexus</name>
      <url>http://주소:8081/repository/home/</url>
      <mirrorOf>*</mirrorOf>
    </mirror>
  </mirrors>

</settings>

 

설정 후 프로젝트에 Maven Dependency를 추가하거나 Jenkins 빌드를 하게 되면 자동으로 Nexus에 라이브러리들이 업로드되어 Nexus Repository를 사용할 수 있는 것을 확인할 수 있다.

 

끝으로..

2가지 방법 중 하나를 선택해 적절히 사용하면 될 것 같다.

1. Local Tomcat 설정

1.1 Tomcat 폴더의 server.xml 설정

1.1.1 GlobalNamingResources 추가

driverClassName엔 사용하는 드라이버를 입력하면된다.

오라클일 경우 : oracle.jdbc.driver.OracleDriver 등.

global과, name 변수에는 똑같은 이름을 넣어준다. 

url이 오라클일 경우 : jdbc:oracle:thin:@IP:PORT:스키마이름

<GlobalNamingResources>

...

<Resource 
auth="Container" 
driverClassName="com.mysql.jdbc.Driver" // mysql, oracle, mariadb, tibero 등등 드라이버입력 
global="global과 name 똑같은 이름" 
maxActive="8"
maxIdle="8" 
maxWait="-1" 
minIdle="0" 
name="global과 name 똑같은 이름" 
password="DB패스워드" 
type="javax.sql.DataSource" url="jdbc:mysql://localhost:3306/myDB" username="DB아이디"/>

</GlobalNamingResources>

 

1.2 Tomcat 폴더의 context.xml 설정

1.2.1 ResourceLink 추가

name과 global 변수엔 server.xml에서 설정한 name,과 global 이름을 똑같이 넣는다.

<Context>

...
<ResourceLink name="위에 설정한 name, global이름과 동일" global="위에 설정한 name, global이름과 동일"
		auth="Container" type="javax.sql.DataSource" />

</Context

 

2. 개발 프로젝트(Eclipse 설정)

2.1 xml 파일에 설정

2.1.1 root-context.xml or context-datasource.xml

root-context.xml 또는 context-datasource.xml에 기존 DB접근하는 설정들을 지우거나 주석처리하고 아래의 코드를 추가한다.

또한, <value>에는 java:comp/env/jdbc/를 붙이고 server.xml에서 설정한 name, global이름과 동일하게 작성한다.

ex) server.xml에서 설정한 이름이 test라면 - java:comp/env/jdbc/test 

<bean id="dataSource"
		class="org.springframework.jndi.JndiObjectFactoryBean">
		<property name="jndiName">
			<value>java:comp/env/jdbc/name,global 이름과 동일</value>
		</property>
</bean>

 

3. 에러 발생 시 처리

3.1 DB Connection 에러

3.1.1 DB connector lib 가 없을 경우

만약 실행 시 connector에러가 발생한다면, Tomcat 폴더에 각 DB의 connector 라이브러리를 추가한다.

톰캣의 lib폴더에 접근한다.

경로 - apache-tomcat-8.5.59\lib

MySQL을 사용한다면 아래의 jar 파일을 톰캣의 lib폴더에 넣는다.

MySQL - mysql-connector-java.jar

 

 

3.2 UserDatabaseRealm 에러

3.2.1 org.apache.catalina.realm.UserDatabaseRealm Start 에러

만약 시작시 org.apache.catalina.realm.UserDatabaseRealm Start 에러가 발생한다면

Tomcat의 server.xml에 Realm부분의 className="org.apache.catalina.realm.UserDatabaseRealm" 을 아래와 같이 주석 처리한다.

<Realm className="org.apache.catalina.realm.LockOutRealm">
<!-- <Realm className="org.apache.catalina.realm.UserDatabaseRealm" -->
<!-- resourceName="UserDatabase" /> -->
</Realm>

 

'Develop > Spring' 카테고리의 다른 글

Spring Security URL login  (0) 2021.01.22
Spring Tomcat JNDI 설정  (0) 2020.11.17
Spring Security Custom Filter  (0) 2020.11.09
Spring security 로그인(DB에 있는 아이디 조회)  (0) 2019.11.02
Spring Mybatis + MariaDB(HikariCP) 설정  (0) 2019.10.24
Spring 3 에서 4로 migration  (0) 2019.10.22

+ Recent posts