Spring Security 로그인 - eunja511005/Tutorial GitHub Wiki
1. 필요한 의존성 추가
- POM.xml 파일에 아래 내용 추가
<!-- security 사용 위해 종속성 포함 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- security test 사용 위해 종속성 포함 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
2. 유저 테이블 생성
- schema.xml 파일에 아래 내용 추가
drop table zthm_user;
CREATE TABLE zthm_user
(
username VARCHAR2(30) NOT NULL,
password VARCHAR2(100),
email VARCHAR2(30),
role VARCHAR2(30),
picture VARCHAR2(50),
enable CHAR(1),
create_id VARCHAR2(30),
create_time VARCHAR2(14),
update_id VARCHAR2(30),
update_time VARCHAR2(14)
);
COMMENT ON TABLE zthm_user IS '유저정보';
COMMENT ON COLUMN zthm_user.username IS '유저이름';
COMMENT ON COLUMN zthm_user.password IS '패스워드';
COMMENT ON COLUMN zthm_user.email IS '이메일';
COMMENT ON COLUMN zthm_user.role IS '역할';
COMMENT ON COLUMN zthm_user.picture IS '사진';
COMMENT ON COLUMN zthm_user.enable IS '사용여부';
COMMENT ON COLUMN zthm_user.create_id IS '생성자';
COMMENT ON COLUMN zthm_user.create_time IS '생성시간';
COMMENT ON COLUMN zthm_user.update_id IS '수정장';
COMMENT ON COLUMN zthm_user.update_time IS '수정시간';
3. 유저 테이블에 테스트 유저 입력
- data.xml 파일에 아래 내용 추가
insert into zthm_user(username, password, email, role, picture, enable, create_id, create_time, update_id, update_time) values('#####.park', '$2a$10$RWq20vPGyVlHLMxPCuyd6e9NFcqpCijj2MeWOMt/AcE4UcdN2qLZq', '#####[email protected]', 'sysadmin', '', '1', '#####.park', to_char(sysdate,'yyyymmddhh24mmss'), '#####.park', to_char(sysdate,'yyyymmddhh24mmss'));
4. 오라클 DB 서버 연결 정보, Mybatis 설정 정보 입력
- application.properties 파일에 아래 내용 추가
# database
spring.datasource.url=jdbc:oracle:thin:@IFreedomDB20230331_medium?TNS_ADMIN=D:/Users/#####/Downloads/Wallet_IFreedomDB20230331
spring.datasource.username=wasadmin
spring.datasource.password=************
# mybatis
mybatis.config=mybatis/mybatis-config.xml
mybatis.mapper-locations=mybatis/mapper/*.xml
- TestMapper.xml 파일에 아래 내용 추가
<select id="getUser" parameterType="hashMap" resultType="com.eun.tutorial.dto.UserInfoDTO">
SELECT username, password, email, role, picture, enable,
create_id, create_time, update_id, update_time
FROM zthm_user
WHERE username = #{username}
</select>
7. 유저 정보 조회를 위한 TestMapper 인터페이스 추가
- TestMapper 파일에 아래 내용 추가
@Mapper
public interface TestMapper {
List<Book> getBookLists();
UserInfoDTO getUser(Map<String, Object> map);
}
8. UserDetails 구현 클래스 생성
package com.eun.tutorial.service.user;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import com.eun.tutorial.dto.UserInfoDTO;
import java.util.Collection;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
public class UserDetailsImpl implements UserDetails {
private UserInfoDTO userInfoDTO;
public UserDetailsImpl(UserInfoDTO user) {
this.userInfoDTO = user;
}
@Override
public boolean equals(Object o){
if(this==o) return true;
if(!(o instanceof UserDetailsImpl)) return false;
UserDetailsImpl userDetails = (UserDetailsImpl) o;
return userInfoDTO.getUsername().equals(userDetails.getUsername()) &&
userInfoDTO.getPassword().equals(userDetails.getPassword());
}
@Override
public int hashCode(){
return Objects.hash(userInfoDTO.getUsername(), userInfoDTO.getPassword());
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Set<GrantedAuthority> roles = new HashSet<>();
for (String role : userInfoDTO.getRole().split(",")){
roles.add(new SimpleGrantedAuthority(role));
}
return roles;
}
@Override
public String getPassword() {
return userInfoDTO.getPassword();
}
@Override
public String getUsername() {
return userInfoDTO.getUsername();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return userInfoDTO.isEnable();
}
}
9. UserDetailsService 구현 클래스 생성
package com.eun.tutorial.service.user;
import java.util.HashMap;
import java.util.Map;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import com.eun.tutorial.dto.UserInfoDTO;
import com.eun.tutorial.mapper.TestMapper;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
private final TestMapper testDao;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Map<String, Object> map = new HashMap();
map.put("username", username); // 가져온 데이터에 키와 벨류값을 지정
UserInfoDTO optionalUser = testDao.getUser(map);
if(optionalUser != null) {
return new UserDetailsImpl(optionalUser);
}else{
return null;
}
}
}
10. spring security에서 인증을 위한 설정 내용 추가
- MyWebSecurityConfigurerAdapter 파일에 아래 내용 추가
/**
* 5.로그인 설정
* 1) 로그인 페이지 설정
* 2) 로그인 페이지에서 로그인을 위해 호출 하는 url 설정
* 3) 나머지는 인증 후 접속 가능토록 설정
* 4) 로그인 성공시 핸들러 설정
* 5) 로그인 실패시 핸들서 설정
* 6) 모두 로그 아웃에 접근 가능
*/
http
.formLogin() // 로그인에 관한 설정
// .loginPage("/loginForm") // 로그인 페이지 링크
// .loginProcessingUrl("/signin")
// .usernameParameter("userId")
.successHandler((request, response, auth)->{
for (GrantedAuthority authority : auth.getAuthorities()){
log.info("Authority Information {} ", authority.getAuthority());
}
log.info("getName {} ",auth.getName());
Map<String, String> res = new HashMap<>();
response.sendRedirect("/");
// Map<String, String> res = new HashMap<>();
// res.put("result", "login success");
// JSONObject json = new JSONObject(res);
// response.setContentType("application/json; charset=utf-8");
// response.getWriter().print(json);
})
.failureHandler((request, response, exception)->{
String errMsg = "";
if(exception.getClass().isAssignableFrom(BadCredentialsException.class)){
errMsg = "Invalid username or password";
//response.setStatus(401);
}else{
errMsg = "UnKnown error - "+exception.getMessage();
//response.setStatus(400);
}
// zthmErrorRepository.save(ZthmError.builder()
// .errorMessage("Login Error : "+exception.getMessage())
// .build());
// Map<String, String> res = new HashMap<>();
// res.put("result", errMsg);
// JSONObject json = new JSONObject(res);
// response.setContentType("application/json; charset=utf-8");
// response.getWriter().print(json);
response.sendRedirect("/login");
})
.permitAll();
11. spring security에서 인증을 위한 bean 추가
- MyWebSecurityConfigurerAdapter 파일에 아래 내용 추가
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
12. 구현 내용
- http://localhost:8080 입력시 로그인 화면으로 이동 됨
- 테스트 입력한 맞는 인증 정보 입력 시 메인 페이지로 이동('/')
- 잘못된 인증 정보 입력시 로그 화면으로 다시 이동('/login')
13. git main 브랜치에 반영
- 로컬에서 서버로 푸쉬
cd D:\Users\ywbes\git\Tutorial
git status
git add src/test/java/com/eun/tutorial/TutorialApplicationTests.java
git status
git commit -m ":new: spring security 활용 로그인 기능 추가"
git push
- 서버에 commit 확인
https://github.com/eunja511005/Tutorial