JAVA/Spring

spring boot + JPA + security 로그인 설정

cocho/kuby 2018. 2. 19. 00:02

Spring security 를 통한 권한부여를 공부하다가 바보처럼 자꾸 잊어버려서 Step by 로 메모해둠



1. 의존성 설치 


build.gradle


compile('org.springframework.boot:spring-boot-starter-security')


2. Security Config 등록

@EnableWebSecurity /* WebConfig 컴포넌트 등록 */
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
UserDetailsService userDetailsService;

@Autowired
PasswordEncoder passwordEncoder;

    /* Password Encoder 등록 */
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}


    /* 인증방식 */
@Autowired
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
}

    /* Security 제외 패턴 */
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers("/resources/**");
}

    /* 각종 시큐어 패턴등록 */
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests() /* 인증 요청 선언?????? */

.antMatchers("/access").hasRole("ADMIN") /* /access 패턴은 ADMIN 유저만 접근 */
.and()

.formLogin() /* 로그인 폼 나오도록 */
.loginPage("/login") /* 내가 만든 로그인 페이지 */
.usernameParameter("email") /* username 을 대체할 아이디 param default username */
.passwordParameter("password") /* password 를 대체할 패스워드 param default password */
.permitAll() /* 모두 오픈 ( 반대는 denyAll() ) */
.and()
.logout().permitAll().logoutSuccessUrl("/"); /* 로그아웃 성공시 리다이렉트 url */
}
}


3. 커스터마이징 할 domain 객체

public class UserDetailsImpl extends User {

/* security 에서 제공하는 User 객체를 상속받아야함 난 이부분에서 진짜 많이 헤맴 ... */


public UserDetails(String username, String password, Collection<? extends GrantedAuthority> authorities) {
super(username, password, authorities);
}

public UserDetails(String username, String password, boolean enabled, boolean accountNonExpired,
boolean credentialsNonExpired, boolean accountNonLocked,
Collection<? extends GrantedAuthority> authorities) {
super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
}

    /* 사실 여기선 이거밖에 안씀. 위에 두개는 어떤거 하는지 모르겠는데 좀더 연구한 후에... */
public UserDetailsImpl (String email, String password, String s) {
super(email, password, AuthorityUtils.createAuthorityList(s));
}
}


4. 커스터마이징 service 레이어 등록


@Service
public class UserDetailsServiceImpl implements UserDetailsService {
/* UserDetailsService 인터페이스를 상속 받아야함.... 왜 멍청하게 난 저걸 Bean 으로 등록하고 사용하려고 했는지... */
@Autowired
MemberRepository memberRepository; /* 그냥 여긴 JPA DB 쿼리 날려서 가져옴. */

    
@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
Member member = memberRepository.findByEmail(email); /* JPA row member data */

/* 그냥 String 으로 security User 를 상속한 도메인 객체에 때려박음... 맞는지는 모르겠음 */
return new UserDetailsImpl(member.getEmail(), member.getPassword(), member.getRole().toString());

}
}


5. 도메인 객체 생성

@Entity
@Table(name = "ag_admin")
@Data
@Component
public class Member {

@Id
@GeneratedValue
private Integer idx;

@Column
private String email;

@Column
private String password;

@Column(nullable = false)
@Enumerated(EnumType.STRING)
private Role role;
}

public enum Role {
ROLE_ADMIN /* 난 그냥 일단 하나만 만들어서 할꺼임. 공부니까 */
}


6. Test DB 데이터 insert

INSERT INTO `tbl_member` (email, password, role) VALUES 
('thtjwls', '$2a$10$2FTNCpjqjgAgWwpsnDMBpetvaS4jOTuHTRC.c4mPsoiPzE9TQ4l5y', 'ROLE_ADMIN');

/*

중요한게 왜 권한관리에서는 antMatchers("/access").hasRole("ADMIN") 라고 등록 해뒀으면서 권한 prefix 가

ROLE_* 로 들어가는지 모르겠음... 이렇게 안넣으면 절대 나의 권한을 찾을수없음...

아시는분 설명좀...

*/


/access 에 jsp 파일만들고

/login.jsp 파일만들고

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!doctype html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<c:if test="${param.error != null}">
${param}
</c:if>
로그인 페이지
<form:form action="/login" method="post">
<input type="text" name="email">
<input type="password" name="password">
<input type="submit" value="로그인">
</form:form>
</body>
</html>


로그인 하면 끝