7월 24일
1.커스텀 UserDetailsService 활용
지금까지 배운방식은 스프링 시큐리티에서 username이라고 부르는 사용자의 정보만을 이용하기 때문에 실제 프로젝트에서 사용자의 이름이나 이메일 등의 자세한 정보를 이용할 경우에는 충분하지 못하다는 단점이 읶음.
이러한 문제를 해결하기 위해서는 직접 UserDetailsService를 구현하는 방식을 이용한는 것이 좋다.
스프링 시큐리티의 UserDetailsService 인터페이스에는 loadUserByUsername() 라는 단 한개의 메서드가 존재 한다.
loadUserByUsername() 메소드의 반환타입은 UserDetails 타입으로
UserDetails 반환타입안에도 getAuthorities(),getPassword(),getUserDetails() 등의 추상메서드를 가지고있어 개발전에 이를 직접구현할지, UserDetails 인터페이스를 구현해둔 스프링 시큐리티의 여러 하위클래스를 이용할지 판단해야한다.
가장 일반적으로 많이 사용되는 방법은 여러 하위 클래스들 중에서 org.springframework.security.core.userdetails.User 클래스를 상속하는 형태이다.
(1)회원 도메인, 회원 Mapper 설계
AuthVO,MemberVO 클래스 작성하기
package com.keduit.domain;
import java.util.List;
import lombok.Data;
@Data
public class MemberVO {
private String userid;
private String userpw;
private String userName;
private boolean enabled;
private Data regDate;
private Data updateDate;
private List<AuthVO> authList;
}
package com.keduit.domain;
public class AuthVO {
private String userid;
private String auth;
}
(2)MemberMapper 인터페이스 만들기
회원에 대한 정보는 MyBatis를 이용해서 처리할 것이므로 MemberMapper를 작성해서 t_member, t_member_auth 테이블에 데이터를 추가하고, 조회할 수 있도록 작성해야함.
member 객체를 가져오는 경우에는 한번에 t_member, t_member_auth 테이블를 조인해서 처리할 수 있는 방식으로 MyBatis 의 ResultMap기능을 사용하함.
하나의 MemberVO 인스턴스는 내부적으로 여러개의 AuthVO를 가진다.
즉,하나의 데이터가 여러개의 하위 데이터를 포함하고 있는 것을 의미함.
package com.keduit.mapper;
import com.keduit.domain.MemberVO;
public interface MemberMapper {
public MemberVO read(String userid);
}
(3)MemberMapper.xml 작성하기
memberMap이라는 이름을 가지는 'resultMap' 은 'result' 와 'collection'을 이용해서 바깥쪽 객체(MemberVO의 인스턴스)와 안쪽객체들(AuthVO의 인스턴스)을 구성할수 있다.
MyBatis에서는 하나의 결과에 부가적으로 여러개의 데이터를 처리하는 경우 1:N의 결과를 처리할 수 있는 resultMap 태그를 지원한다.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.keduit.mapper.MemberMapper">
<resultMap type="com.keduit.domain.MemberVO" id="memberMap">
<id property="userid" column="userid" />
<result property="userid" column="userid" />
<result property="userpw" column="userpw" />
<result property="userName" column="username" />
<result property="regDate" column="regdate" />
<result property="updateDate" column="updatedate" />
<collection property="authList" resultMap="authMap">
</collection>
</resultMap>
<resultMap type="com.keduit.domain.AuthVO" id="authMap">
<result property="userid" column="userid" />
<result property="auth" column="auth" />
</resultMap>
<select id="read" resultMap="memberMap">
SELECT mem.userid, userpw, username, enabled, regdate, updatedate, auth
from t_member mem LEFT OUTER JOIN t_member_auth auth on mem.userid=auth.userid
where mem.userid = #{userid}
</select>
</mapper>
(4)MemberMapper 테스트
package com.keduit.mapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.keduit.domain.MemberVO;
import lombok.Setter;
import lombok.extern.log4j.Log4j;
@RunWith(SpringJUnit4ClassRunner.class)//이 클래스로 잘돌아가는지 test해볼꺼야
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/root-context.xml")//참고할 경로는 여기야
@Log4j //화면에 뿌려주는건 Log4j가 관리 할거야
public class MemberMapperTest {
@Setter(onMethod_ =@Autowired )
private MemberMapper mapper;
@Test
public void testRead() {
MemberVO vo= mapper.read("admin90");
log.info(vo);
vo.getAuthList().forEach(authVO ->log.info(authVO));
}
}