1. pom.xml 설정
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>5.4.2</version>
</dependency>
2. Config 설정
package com.kangong.common.security.config;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import com.kangong.common.security.hanndler.CustomLoginSuccessHandler;
import com.kangong.common.security.hanndler.CustomNoOpPasswordEncoder;
import com.kangong.common.security.hanndler.CustomUserDetailsService;
import lombok.Setter;
import lombok.extern.log4j.Log4j2;
@Configuration
@EnableWebSecurity
@Log4j2
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Setter(onMethod_ = { @Autowired })
private DataSource dataSource;
@Bean
public UserDetailsService customUserService() {
return new CustomUserDetailsService();
}
// in custom userdetails
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(customUserService()).passwordEncoder(passwordEncoder());
}
// @Override
// protected void configure(AuthenticationManagerBuilder auth) throws Exception
// {
// log.info("configure JDBC ............................");
//
// String queryUser = "select userid , userpw , enabled from tbl_member where
// userid = ? ";
// String queryDetails = "select userid, auth from tbl_member_auth where userid
// = ? ";
//
// auth.jdbcAuthentication().dataSource(dataSource).passwordEncoder(passwordEncoder())
// .usersByUsernameQuery(queryUser).authoritiesByUsernameQuery(queryDetails);
// }
@Bean
public AuthenticationSuccessHandler loginSuccessHandler() {
return new CustomLoginSuccessHandler();
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/security/all").permitAll()
.antMatchers("/security/admin")
.access("hasRole('ROLE_ADMIN')")
.antMatchers("/security/member")
.access("hasRole('ROLE_MEMBER')");
http.formLogin()
.loginPage("/security/customLogin")
.loginProcessingUrl("/login")
.successHandler(loginSuccessHandler());
http.logout()
.logoutUrl("/security/customLogout")
.invalidateHttpSession(true)
.deleteCookies("remember-me","JSESSION_ID");
http.rememberMe()
.key("kangong")
.tokenRepository(persistentTokenRepository())
.tokenValiditySeconds(604800);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new CustomNoOpPasswordEncoder();
//return new BCryptPasswordEncoder();
}
@Bean
public PersistentTokenRepository persistentTokenRepository() {
JdbcTokenRepositoryImpl repo = new JdbcTokenRepositoryImpl();
repo.setDataSource(dataSource);
return repo;
}
}
3. CustomUserDetailsService 설정
package com.kangong.common.security.hanndler;
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.kangong.common.security.model.CustomUser;
import com.kangong.common.security.model.MemberVO;
import com.kangong.common.security.service.MemberService;
import lombok.Setter;
import lombok.extern.log4j.Log4j2;
@Log4j2
public class CustomUserDetailsService implements UserDetailsService {
@Setter(onMethod_ = { @Autowired })
private MemberService memberService;
@Override
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
log.info("Load User By UserName : " + userName);
// userName means userid
MemberVO vo = memberService.read(userName);
log.info("queried by member mapper: " + vo);
return vo == null ? null : new CustomUser(vo);
}
}
4. PassworEncoder 설정
1)NoOpCustomNoOpPasswordEncoder (encrypt 없이)
package com.kangong.common.security.hanndler;
import org.springframework.security.crypto.password.PasswordEncoder;
import lombok.extern.log4j.Log4j2;
@Log4j2
public class CustomNoOpPasswordEncoder implements PasswordEncoder {
public String encode(CharSequence rawPassword) {
log.warn("before encode :" + rawPassword);
return rawPassword.toString();
}
public boolean matches(CharSequence rawPassword, String encodedPassword) {
log.warn("matches: " + rawPassword + ":" + encodedPassword);
return rawPassword.toString().equals(encodedPassword);
}
}
5. CustomLoginSuccessHandler
package com.kangong.security;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import lombok.extern.log4j.Log4j2;
@Log4j2
public class CustomLoginSuccessHandler implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication auth)
throws IOException, ServletException {
log.warn("Login Success");
List<String> roleNames = new ArrayList<>();
auth.getAuthorities().forEach(authority -> {
roleNames.add(authority.getAuthority());
});
log.warn("ROLE NAMES: " + roleNames);
if (roleNames.contains("ROLE_ADMIN")) {
response.sendRedirect("/sample/admin");
return;
}
if (roleNames.contains("ROLE_MEMBER")) {
response.sendRedirect("/sample/member");
return;
}
response.sendRedirect("/");
}
}
6. CustomAccessDeniedHandler
package com.kangong.common.security.hanndler;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import lombok.extern.log4j.Log4j2;
@Log4j2
public class CustomAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request,
HttpServletResponse response, AccessDeniedException accessException)
throws IOException, ServletException {
log.error("Access Denied Handler");
log.error("Redirect....");
System.out.println("/security/accessError");
response.sendRedirect("/security/accessError");
}
}
7. Model 설정
1) AuthVO
package com.kangong.common.security.model;
import lombok.Data;
@Data
public class AuthVO {
private String userid;
private String auth;
}
2) MemberVO
package com.kangong.common.security.model;
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;
}
3) CustomUser
package com.kangong.common.security.model;
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 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;
}
}
8. Jsp 설정
1)CustomLogin.jsp 설정
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!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>Custom Login Page</h1>
<h2><c:out value="${error}"/></h2>
<h2><c:out value="${logout}"/></h2>
<form method='post' action="/login">
<div>
<input type='text' name='username' value='member00'>
</div>
<div>
<input type='password' name='password' value='pw00'>
</div>
<div>
<div>
<input type='checkbox' name='remember-me'> Remember Me
</div>
<div>
<input type='submit'>
</div>
<input type="hidden" name="${_csrf.parameterName}"
value="${_csrf.token}" />
</form>
</body>
</html>
2)CustomLogout.jsp 설정
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!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> Logout Page</h1>
<form action="/security/customLogout" method='post'>
<input type="hidden"name="${_csrf.parameterName}"value="${_csrf.token}"/>
<button>로그아웃</button>
</form>
</body>
</html>
3)accessError.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" %>
<%@ page import="java.util.*" %>
<!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>Access Denied Page</h1>
<h2><c:out value="${SPRING_SECURITY_403_EXCEPTION.getMessage()}"/></h2>
<h2><c:out value="${msg}"/></h2>
</ul>
</body>
</html>
4)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>/security/all page</h1>
<sec:authorize access="isAnonymous()">
<a href="/customLogin">로그인</a>
</sec:authorize>
<sec:authorize access="isAuthenticated()">
<a href="/security/customLogout">로그아웃</a>
</sec:authorize>
</body>
</html>
5)member.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!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>/security/member page</h1>
</body>
</html>
3)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>/security/admin page</h1>
<p>principal : <sec:authentication property="principal"/></p>
<p>MemberVO : <sec:authentication property="principal.member"/></p>
<p>사용자이름 : <sec:authentication property="principal.member.userName"/></p>
<p>사용자아이디 : <sec:authentication property="principal.username"/></p>
<p>사용자 권한 리스트 : <sec:authentication property="principal.member.authList"/></p>
<a href="/security/customLogout">Logout</a>
</body>
</html>
'개발 > Spring Boot' 카테고리의 다른 글
10.SQL Log 설정 (0) | 2021.02.12 |
---|---|
9. Annotation 설정 (0) | 2021.02.12 |
7.aop 설정 (0) | 2021.02.11 |
6.thymeleaf 설정 (0) | 2021.02.11 |
5. Lombok 설정 (0) | 2021.02.11 |