보라코딩
스프링 시큐리티 커스텀 UserDetailsService 활용 본문
MemberVO.java
package com.mystudy.domain;
import java.util.Date;
import java.util.List;
import lombok.Data;
@Data
public class MemberVO {
private String userid;
private String userpw;
private String userName;
private boolean enabled;
private Date regDate;
private Date updateDate;
private List<AuthVO> authList;
}
AuthVO.java
package com.mystudy.domain;
import lombok.Data;
@Data
public class AuthVO {
private String userid;
private String auth;
}
MemberMapper.java (인터페이스)
package com.mystudy.mapper;
import com.mystudy.domain.MemberVO;
public interface MemberMapper {
public MemberVO read(String userid);
}
MemberMapper.xml
join했고
resultMap 속성에 미리 만들어둔 memberMap을 사용하면
1:N 처리 가능하다!
<?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.mystudy.mapper.MemberMapper">
<resultMap type="com.mystudy.domain.MemberVO" id ="memberMap">
<id property="userid" column="userid" />
<result property="userid" column="userid" />
<result property="userpw" column="userpw" />
<result property="useranme" column="useranme" />
<result property="regdate" column="regdate" />
<result property="updateDate" column="updatedate" />
<collection property="authList" resultMap="authMap">
</collection>
</resultMap>
<resultMap type="com.mystudy.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
tbl_member mem left outer join tbl_member_auth auth
on mem.userid = auth.userid
where mem.userid = #{userid}
</select>
</mapper>
MemberMapperTests.java
package com.mystudy.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.mystudy.domain.MemberVO;
import lombok.extern.log4j.Log4j;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/root-context.xml")
@Log4j
public class MemberMapperTests {
@Autowired
private MemberMapper mapper;
@Test
public void testRead() {
MemberVO vo = mapper.read("admin90");
log.info(vo);
vo.getAuthList().forEach(authVO -> log.info(authVO));
}
}
CustomUserDetailsService 구성 (스프링 시큐리티 구현)
package com.mystudy.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import com.mystudy.domain.MemberVO;
import com.mystudy.mapper.MemberMapper;
import com.mystudy.security.domain.CustomUser;
import lombok.Setter;
import lombok.extern.log4j.Log4j;
@Log4j
public class CustomUserDetailsService implements UserDetailsService{
@Setter(onMethod_ = { @Autowired })
private MemberMapper memberMapper;
@Override
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
log.warn("Load User By UserName : " + userName);
// userName means userid
MemberVO vo = memberMapper.read(userName);
log.warn("queried by member mapper: " + vo);
return vo == null ? null : new CustomUser(vo);
}
}
security-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="customAccessDenied"
class="com.mystudy.security.CustomAccessDeniedHandler"></bean>
<bean id="customLoginSuccess"
class="com.mystudy.security.CustomLoginSuccessHandler"></bean>
<bean id="bcryptPasswordEncoder"
class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" />
<bean id="customUserDetailsService"
class="com.mystudy.security.CustomUserDetailsService" />
<security:http>
<security:intercept-url pattern="/sample/all"
access="permitAll" />
<security:intercept-url
pattern="/sample/member" access="hasRole('ROLE_MEMBER')" />
<security:intercept-url pattern="/sample/admin"
access="hasRole('ROLE_ADMIN')" />
<security:access-denied-handler
ref="customAccessDenied" />
<security:form-login login-page="/customLogin"
authentication-success-handler-ref="customLoginSuccess" />
<security:logout logout-url="/customLogout"
invalidate-session="true" />
</security:http>
<security:authentication-manager>
<security:authentication-provider
user-service-ref="customUserDetailsService" >
<security:password-encoder ref="bcryptPasswordEncoder" />
</security:authentication-provider>
</security:authentication-manager>
</beans>
CustomerUser.java (security 패키지 안에 domain 만들어서)
package com.mystudy.security.domain;
import java.util.Collection;
import java.util.stream.Collectors;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import com.mystudy.domain.MemberVO;
import lombok.Getter;
@Getter
public class CustomUser extends User{
private static final long serialVersionUID = 1L;
private MemberVO member;
public CustomUser(String username, String password,
Collection<? extends GrantedAuthority> authorities) {
super(username, password, authorities);
}
public CustomUser(MemberVO vo) {
super(vo.getUserid(), vo.getUserpw(), vo.getAuthList().stream()
.map(auth -> new SimpleGrantedAuthority(auth.getAuth()))
.collect(Collectors.toList()));
this.member = vo;
}
}
admin.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://www.springframework.org/security/tags" prefix="sec" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>/sample/admin page</h1>
<p>principal : <sec:authentication property="principal"/></p>
<p>사용자아이디 : <sec:authentication property="principal.username"/></p>
<p>사용자 권한 리스트 : <sec:authentication property="principal.member.authList"/></p>
<p>사용자이름 : <sec:authentication property="principal.member.userName"/></p>
<p>MemberVO : <sec:authentication property="principal.member"/></p>
<a href="/customLogout">Logout</a>
</body>
</html>
all.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://www.springframework.org/security/tags" prefix="sec" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<!-- all or member or admin -->
<h1>/sample/all page</h1>
<!-- 익명의 사용자의 경우(로그인 안한경우도) -->
<sec:authorize access="isAnonymous()">
<a href="/customLogin">로그인</a>
</sec:authorize>
<!-- 인증된 사용자의 경우 -->
<sec:authorize access="isAuthenticated()">
<a href="/customLogout">로그아웃</a>
</sec:authorize>
</body>
</html>
같은 주소로 들어가도 (/sample/all)
로그인된 사람과 로그인 안된사람의 화면이 다름
'코딩 > Spring' 카테고리의 다른 글
Day99 _ 3차 프로젝트 시작 (2023.05.18 ~ 2023.06.21) (0) | 2023.05.18 |
---|---|
스프링 시큐리티 자동 로그인(remember-me) (0) | 2023.05.17 |
스프링 Ajax 쉬운 설명 (0) | 2023.05.17 |
스프링 UriComponentsBuilder를 이용한 링크 생성 (0) | 2023.05.16 |
스프링 검색처리 (0) | 2023.05.16 |