티스토리 뷰

 
지난번 4. Spring Boot Security에서는 Authority를 바로 받아올 수 없어 String으로 받아왔습니다.
이 부분은 왠지 마음에 들지 않습니다. 그래서 TypeHandler를 이용해서 GrantedAuthority를 바로 받아오고, 그로 인해 깔끔해진 코드를 보겠습니다.

1. 먼저 SimpleGrantedAuthority의 TypeHandler를 정의합니다. TypeHandler는 http://www.mybatis.org/mybatis-3/ko/configuration.html#typeHandlers 에 잘 나와 있습니다. 패키지는 config 안에 두겠습니다.
package com.cusonar.example.config;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.springframework.security.core.authority.SimpleGrantedAuthority;

@MappedJdbcTypes(JdbcType.VARCHAR)
public class AuthorityTypeHandler extends BaseTypeHandler<SimpleGrantedAuthority> {

     @Override
     public void setNonNullParameter(PreparedStatement ps, int i,
               SimpleGrantedAuthority parameter, JdbcType jdbcType) throws SQLException {
          ps.setString(i, parameter.getAuthority());
     }

     @Override
     public SimpleGrantedAuthority getNullableResult(ResultSet rs, String columnName)
               throws SQLException {
          return new SimpleGrantedAuthority(rs.getString(columnName));
     }

     @Override
     public SimpleGrantedAuthority getNullableResult(ResultSet rs, int columnIndex)
               throws SQLException {
          return new SimpleGrantedAuthority(rs.getString(columnIndex));
     }

     @Override
     public SimpleGrantedAuthority getNullableResult(CallableStatement cs,
               int columnIndex) throws SQLException {
          return new SimpleGrantedAuthority(cs.getString(columnIndex));
     }
}
     . 기본적으로 BaseTypeHandler을 상속받습니다. Generic 타입은 SimpleGrantedAuthority 로 합니다.
     . 그러면 구현해야 하는 메소드가 4개 있습니다. PreparedStatement에 파라미터를 어떻게 넣을것인지, ResultSet에서 데이터는 어떻게 가져올건지입니다.


2. 해당 TypeHandler를 MyBatis Config에 추가해줍니다. 
mybatis.type-handlers-package=com.cusonar.example.config

3. TypeHandler를 정의했으니 UserMapper에서 List<String>으로 한 부분을 List<GrantedAuthority> 로 변경해줍니다.
<select id="readAuthority" parameterType="String" resultType="org.springframework.security.core.authority.SimpleGrantedAuthority">
     SELECT authority_name FROM authority WHERE username = #{username}
</select>
     . resultType으로 GrantedAuthority를 넣어줍니다. TypeAlias 하지 않았으므로 패키지이름과 같이 써주어야 합니다.

package com.cusonar.example.user.mapper;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;
import org.springframework.security.core.GrantedAuthority;

import com.cusonar.example.user.domain.User;

@Mapper
public interface UserMapper {
     public User readUser(String username);
     public List<GrantedAuthority> readAuthority(String username);
}

4. Mapper가 수정되었으니 Service도 수정해줍니다. 

package com.cusonar.example.user.service;
 
import java.util.Collection;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import com.cusonar.example.user.domain.User;
import com.cusonar.example.user.mapper.UserMapper;
 
@Service
public class UserServiceImpl implements UserService {
     
     @Autowired UserMapper userMapper;
 
     @Override
     public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
          User user = userMapper.readUser(username);
          user.setAuthorities(getAuthorities(username));
          
          return user;
     }
     
     public Collection<GrantedAuthority> getAuthorities(String username) {
    	 Collection<GrantedAuthority> authorities = userMapper.readAuthority(username);
    	 return authorities;
     }
}

 

 
5. 이제 테스트 코드를 수정해서 정상적으로 되는지 확인합니다.
package com.cusonar.example.user;
  
import static org.hamcrest.CoreMatchers.hasItem;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

import java.util.List;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;

import com.cusonar.example.ExampleApplication;
import com.cusonar.example.user.domain.User;
import com.cusonar.example.user.mapper.UserMapper;
  
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = ExampleApplication.class)
@WebAppConfiguration
public class UserMapperTest {
      
     @Autowired UserMapper userMapper;
      
     @Test
     public void readUserTest() {
          User user = userMapper.readUser("cusonar");
          assertThat("cusonar", is(user.getUsername()));
          assertThat("YCU", is(user.getName()));
          assertThat("1234", is(user.getPassword()));
     }
      
     
     public void readAuthorityTest() {
          List<GrantedAuthority> authorities = userMapper.readAuthority("cusonar");
          Iterator<GrantedAuthority> it = authorities.iterator();
          while (it.hasNext()) {
               GrantedAuthority authority = it.next();
               assertThat(authorities, hasItem(new SimpleGrantedAuthority(authority.getAuthority())));
          }
     }
}

잘 되네요. 이렇게 MyBatis에서 기본적으로 제공하지 않는 Type을 사용할때는 TypeHandler를 사용하시면 됩니다.

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/03   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
글 보관함