본문 바로가기
Spring Framework/project

Spring Security -인증 및 권한부여

by bloodFinger 2020. 1. 6.

 

UserDetailsService 인터페이스는 DB에서 유저 정보를 가져오는 역할을 한다. 해당 인터페이스의 메소드에서 DB의 유저 정보를 가져와서 AuthenticationProvider 인터페이스로 유저 정보를 리턴

 

- 인증 및 권한부여 절차

UserDetails

Spring Security에서 사용자의 정보를 담는 인터페이스는 UserDetails 인터페이스이다.

우리가 이 인터페이스를 구현하게 되면 Spring Security에서 구현한 클래스를 사용자 정보로 인식하고 인증 작업을 한다.

쉽게 말하면 UserDetails 인터페이스는 VO 역할을 한다고 보면 된다.

@SuppressWarnings("serial")
@Data
@Component
public class MemberDTO implements UserDetails {
	private String member_email;
	private String member_pwd;
	private String member_name;
	private String member_nickname;
	private String member_profile;
	private int member_flag;
	private int member_seq;
	private Date logtime;
	private String memberAuthKey; // 이메일 인증키
	private int memberAuthStatus; // 이메일 인증상태
	private String memberAuthority; // 멤버 권한

	@Override
	public Collection<? extends GrantedAuthority> getAuthorities() {
		List<GrantedAuthority> auth = new ArrayList<GrantedAuthority>();

		if (this.member_nickname.equals("admin")) {
			auth.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
		} else {
			auth.add(new SimpleGrantedAuthority("ROLE_USER"));
		}
		
		return auth;
	}

	@Override
	public String getPassword() {
		return "{noop}" + member_pwd;
	}

	@Override
	public String getUsername() {
		return member_email;
	}

	@Override
	public boolean isAccountNonExpired() {
		return true;
	}

	@Override
	public boolean isAccountNonLocked() {
		return true;
	}

	@Override
	public boolean isCredentialsNonExpired() {
		return true;
	}

	@Override
	public boolean isEnabled() {
		return true;
	}
}

 

UserDetails 인터페이스를 구현하게 되면 오버라이드되는 메소드들에 대해 간략하게 설명!

 

+ 오버라이드되는 메소드들만 Spring Security에서 알아서 이용하기 때문에 따로 클래스를 만들지 않고 멤버변수를 추가해서 같이 사용해도 무방하다. 만든 멤버변 수들은 getter, setter를 만들어서 사용하면 된다

매소드명 리턴타입 설명
getAuthorities()

 Collection<? extends   GrantedAuthority>

계정이 가지고 있는 권한 목록 리턴
getPassword() String 계정의 비밀번호 리턴
getUsername() String 계정의 이름 리턴
isAccountNonExpired() boolean  계정이 만료되지 않았는지 리턴(true:만료x)
isAccountNonLocked() boolean 계정이 잠겨있지 않았는지 리턴(true : 잠김x)
isCredentialNonExpired() boolean  비밀번호가 만료되지 않았는지 리턴(true: 만료x)
isEnabled() boolean 계정이 활성화(사용가능)인지 리턴(true:활성화)

 

CustomUserDetailService.java

//유저정보를 DB를 가지고 오는 클래스
public class CustomUserDetailsService implements UserDetailsService {
	@Autowired
	private MemberDAO memberDAO;

	@Override
	public UserDetails loadUserByUsername(String member_email) throws UsernameNotFoundException {
		MemberDTO member = memberDAO.getMemberByEmail(member_email);
		
		if (member == null) {
			throw new UsernameNotFoundException(member_email);
		}

		return member;
	}

}

 

 

MemberDAOMybatis

// 이메일로 회원 정보 가지고 오기.
@Override
public MemberDTO getMemberByEmail(String member_email) {
	return sqlSession.selectOne("memberSQL.getMemberByEmail", member_email);
}

 

MemberDAOMapper.xml

<!-- 이메일로 회원정보 가지고 오기 -->
<select id="getMemberByEmail" parameterType="String" resultType="member">
	select * from mentors_member where member_email = #{member_email}
</select>

 

security.xml

<authentication-manager>
    <authentication-provider ref="customMemberAuthProvider"/>
    //유저 정보를 가져오는 클래스를 설정하는 곳
    <authentication-provider user-service-ref="customMemberService"/>
</authentication-manager>

<beans:bean id="customMemberService" class="member.service.CustomUserDetailsService"/>

 

 

 

AuthenticationProvider

AuthertucationProvider 인터페이스는 화면에서 입력한 로그인 정보와 DB에서 가져온 사용자의 정보를 비교해주는 인터페이스!!

  • authenticate()  :  화면에서 사용자가 입력한 로그인 정보를 담고 있는 Authentication 객체를 가지고 있다.
  • supports(class<?> authentication ) : AuthenticationProvider 인터페이스가 지정된 Authentication 객체를 지원하는 경우에 true를 리턴한다.

+ DB에서 사용자의 정보를 가져오는 건 위에서 구현했던 UserDetailsService 인터페이스에서 loadUserByUsername() 메서드를 통해 구현했었다

public class CustomAuthenticationProvider implements AuthenticationProvider {
	@Autowired
	private CustomUserDetailsService customUserDetailsService;
	@Autowired
	private PasswordEncoder passwordEncoder;

	@Override
	public Authentication authenticate(Authentication authentication) throws AuthenticationException {
		String member_email = (String) authentication.getPrincipal();
		String member_pwd = (String) authentication.getCredentials();

		MemberDTO member = (MemberDTO) customUserDetailsService.loadUserByUsername(member_email);
                //bcrypt의 비밀번호 체크 메소드
		if (!passwordEncoder.matches(member_pwd, member.getMember_pwd())) {
			throw new BadCredentialsException(member_email);
		}

		if (member.getMemberAuthStatus() == 0) {
			throw new DisabledException(member_email);
		}
        
                //권한 부여: memberDTO의 getAuthorities() 메소드에서 담당. 
		List<GrantedAuthority> roles = (List<GrantedAuthority>) member.getAuthorities();
		// 스프링 시큐리티 내부 클래스로 인증 토큰 생성
		UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(member_email, member_pwd, roles);

		return result;
	}

	@Override
	public boolean supports(Class<?> authentication) {
		return true;
	}

}

 

security.xml

	<authentication-manager>
		<authentication-provider ref="customMemberAuthProvider"/>
        <authentication-provider user-service-ref="customMemberService"/>
    </authentication-manager>
    
	<beans:bean id="bcryptPasswordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
	<beans:bean id="customMemberService" class="member.service.CustomUserDetailsService"/>
	<beans:bean id="customMemberAuthProvider" class="member.service.CustomAuthenticationProvider"/>

 

 

 

'Spring Framework > project' 카테고리의 다른 글

CSRF 는 무엇인가?  (0) 2020.02.12
Spring 실시간 알림(webSocket)  (15) 2020.01.26
Spring Security - LoginFailureHandler  (0) 2020.01.06
Spring Security - LoginSucessHandler  (0) 2020.01.06
spring security 환경설정  (0) 2020.01.06