DBInit
@Component
@RequiredArgsConstructor
public class DBInit implements CommandLineRunner {
private final UserService userService;
private final SchoolService schoolService;
private final PasswordEncoder passwordEncoder;
@Override
public void run(String... args) throws Exception {
School defaultSchool = schoolService.findSchool(1L).orElseGet(()->
schoolService.save(School.builder()
.name("테스트 학교")
.city("서울")
.build())
);
userService.findByEmail("admin@test.com").or(()->{
User admin = User.builder()
.name("admin")
.email("admin@test.com")
.password(passwordEncoder.encode("1234"))
.enabled(true)
.school(defaultSchool)
.build();
admin = userService.save(admin);
admin.setAuthorities(Set.of(
new Authority(admin.getUserId(), Authority.ROLE_ADMIN),
new Authority(admin.getUserId(), Authority.ROLE_TEACHER),
new Authority(admin.getUserId(), Authority.ROLE_STUDENT)));
return Optional.of(userService.save(admin));
});
userService.findByEmail("teacher@test.com").or(()->{
User teacher = User.builder()
.name("teacher")
.email("teacher@test.com")
.password(passwordEncoder.encode("1234"))
.enabled(true)
.school(defaultSchool)
.build();
teacher = userService.save(teacher);
teacher.setAuthorities(Set.of(
new Authority(teacher.getUserId(), Authority.ROLE_TEACHER)
));
return Optional.of(userService.save(teacher));
});
userService.findByEmail("study@test.com").or(()->{
User study = User.builder()
.name("study")
.email("study@test.com")
.password(passwordEncoder.encode("1234"))
.enabled(true)
.school(defaultSchool)
.build();
study = userService.save(study);
study.setAuthorities(Set.of(
new Authority(study.getUserId(), Authority.ROLE_STUDENT)
));
return Optional.of(userService.save(study));
});
}
}
public class LoginFailureHandler implements AuthenticationFailureHandler {
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
protected Log logger = LogFactory.getLog(this.getClass());
@Override
public void onAuthenticationFailure(
HttpServletRequest request,
HttpServletResponse response,
AuthenticationException exception
) throws IOException, ServletException {
handle(request, response);
clearAuthenticationAttributes(request);
}
protected void clearAuthenticationAttributes(HttpServletRequest request) {
HttpSession session = request.getSession(false);
if (session == null) {
return;
}
session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
}
protected void handle(
HttpServletRequest request,
HttpServletResponse response
) throws IOException {
String targetUrl = determineTargetUrl(request);
if (response.isCommitted()) {
logger.debug("Response has already been committed. Unable to redirect to "+ targetUrl);
return;
}
redirectStrategy.sendRedirect(request, response, targetUrl);
}
protected String determineTargetUrl(final HttpServletRequest request) {
if(request.getParameter("site").equals("manager")) {
return "/login?site=manager&error=true";
}else if(request.getParameter("site").equals("study")){
return "/login?site=study&error=true";
}else if(request.getParameter("site").equals("teacher")){
return "/login?site=teacher&error=true";
}
return "/";
}
}
public class LoginSuccessHandler implements AuthenticationSuccessHandler {
private RequestCache requestCache = new HttpSessionRequestCache();
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
protected Log logger = LogFactory.getLog(this.getClass());
@Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response,
Authentication authentication)
throws IOException {
handle(request, response, requestCache.getRequest(request, response), authentication);
clearAuthenticationAttributes(request);
}
@Override
public void onAuthenticationSuccess(
HttpServletRequest request,
HttpServletResponse response,
FilterChain chain,
Authentication authentication
) throws IOException, ServletException {
// System.out.println("success... 1");
}
protected void clearAuthenticationAttributes(HttpServletRequest request) {
HttpSession session = request.getSession(false);
if (session == null) {
return;
}
session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
}
protected void handle(
HttpServletRequest request,
HttpServletResponse response,
SavedRequest savedRequest,
Authentication authentication
) throws IOException {
String targetUrl = determineTargetUrl(request, savedRequest, authentication);
if (response.isCommitted()) {
logger.debug("Response has already been committed. Unable to redirect to "+ targetUrl);
return;
}
redirectStrategy.sendRedirect(request, response, targetUrl);
}
protected String determineTargetUrl(final HttpServletRequest request, SavedRequest savedRequest, final Authentication authentication) {
if(savedRequest != null) {
String redirectUrl = savedRequest.getRedirectUrl();
if(redirectUrl != null && !redirectUrl.startsWith("/login")) {
return savedRequest.getRedirectUrl();
}
}
if(request.getParameter("site").equals("manager")) {
return "/manager";
}else if(request.getParameter("site").equals("study")){
return "/study";
}else if(request.getParameter("site").equals("teacher")){
return "/teacher";
}
return "/";
}
}
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@RequiredArgsConstructor
public class OnlinePaperSecurityConfig extends WebSecurityConfigurerAdapter {
private final UserSecurityService userSecurityService;
@Bean
PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userSecurityService)
.passwordEncoder(passwordEncoder());
}
private RememberMeServices rememberMeServices(){
TokenBasedRememberMeServices rememberMeServices = new TokenBasedRememberMeServices(
"paper-site-remember-me",
userSecurityService
);
rememberMeServices.setParameter("remember-me");
rememberMeServices.setAlwaysRemember(true);
rememberMeServices.setTokenValiditySeconds(3600);
return rememberMeServices;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
final SpLoginFilter filter = new SpLoginFilter(
authenticationManagerBean(),
rememberMeServices()
);
http
.csrf().disable()
.formLogin(login->{
login.loginPage("/login")
;
})
.logout(logout->{
logout.logoutSuccessUrl("/")
;
})
.rememberMe(config->{
config.rememberMeServices(rememberMeServices())
;
})
.addFilterAt(filter, UsernamePasswordAuthenticationFilter.class)
.exceptionHandling(exception->{
exception.accessDeniedPage("/access-denied");
})
.authorizeRequests(config->{
config
.antMatchers("/").permitAll()
.antMatchers("/login").permitAll()
.antMatchers("/error").permitAll()
.antMatchers("/signup/*").permitAll()
.antMatchers("/study/**").hasAnyAuthority("ROLE_ADMIN", "ROLE_STUDENT")
.antMatchers("/teacher/**").hasAnyAuthority("ROLE_ADMIN", "ROLE_TEACHER")
.antMatchers("/manager/**").hasAuthority("ROLE_ADMIN")
;
})
;
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.requestMatchers(PathRequest.toStaticResources().atCommonLocations());
}
}
public class SpLoginFilter extends UsernamePasswordAuthenticationFilter {
private final AuthenticationManager authenticationManager;
public SpLoginFilter(
AuthenticationManager authenticationManager,
RememberMeServices rememberMeServices
){
this.authenticationManager = authenticationManager;
this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/login","POST"));
this.setAuthenticationSuccessHandler(new LoginSuccessHandler());
this.setAuthenticationFailureHandler(new LoginFailureHandler());
this.setRememberMeServices(rememberMeServices);
}
@SneakyThrows
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
UserLogin userLogin = UserLogin.builder()
.username(request.getParameter("username"))
.password(request.getParameter("password"))
.site(request.getParameter("site"))
.rememberme(request.getParameter("remember-me") != null)
.build();
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
userLogin.getUsername(), userLogin.getPassword(), null
);
return authenticationManager.authenticate(authToken);
}
@Override
protected void successfulAuthentication(
HttpServletRequest request,
HttpServletResponse response,
FilterChain chain,
Authentication authResult) throws IOException, ServletException
{
super.successfulAuthentication(request, response, chain, authResult);
}
@Override
protected void unsuccessfulAuthentication(
HttpServletRequest request,
HttpServletResponse response,
AuthenticationException failed) throws IOException, ServletException
{
super.unsuccessfulAuthentication(request, response, failed);
}
public static String getIp(HttpServletRequest request) {
String ip = request.getHeader("X-Forwarded-For");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class UserLogin {
private String username;
private String password;
private String site;
private boolean rememberme;
}
Controller의 HomeController
@Controller
@RequiredArgsConstructor
public class HomeController {
private final SchoolService schoolService;
private final UserService userService;
private final PasswordEncoder passwordEncoder;
private RequestCache requestCache = new HttpSessionRequestCache();
@GetMapping("/")
public String home(Model model){
return "index";
}
@ResponseBody
@GetMapping(value="/schools")
public List<School> getSchoolList(@RequestParam(value="city", required = true) String city){
return schoolService.getSchoolList(city);
}
@ResponseBody
@GetMapping(value="/teachers")
public List<UserData> getTeacherList(@RequestParam(value="schoolId", required = true) Long schoolId){
return userService.findBySchoolTeacherList(schoolId).stream()
.map(user->new UserData(user.getUserId(), user.getName()))
.collect(Collectors.toList());
}
@GetMapping("/login")
public String login(
@AuthenticationPrincipal User user,
@RequestParam(value="site", required = false) String site,
@RequestParam(value="error", defaultValue = "false") Boolean error,
HttpServletRequest request,
Model model
){
if(user!=null && user.isEnabled()){
if(user.getAuthorities().contains(Authority.ADMIN_AUTHORITY)){
return "redirect:/manager";
}else if(user.getAuthorities().contains(Authority.TEACHER_AUTHORITY)){
return "redirect:/teacher";
}else if(user.getAuthorities().contains(Authority.STUDENT_AUTHORITY)){
return "redirect:/study";
}
}
if(site == null) {
SavedRequest savedRequest = requestCache.getRequest(request, null);
if(savedRequest != null) {
site = estimateSite(savedRequest.getRedirectUrl());
}
}
model.addAttribute("error", error);
model.addAttribute("site", site);
return "loginForm";
}
private String estimateSite(String referer) {
if(referer == null)
return "study.html";
try {
URL url = new URL(referer);
String path = url.getPath();
if(path != null){
if(path.startsWith("/teacher")) return "teacher";
if(path.startsWith("/study")) return "study";
if(path.startsWith("/manager")) return "manager";
}
String query = url.getQuery();
if(query != null){
if(path.startsWith("/site=teacher")) return "teacher";
if(path.startsWith("/site=study")) return "study";
if(path.startsWith("/site=manager")) return "manager";
}
} catch (MalformedURLException e) {
e.printStackTrace();
}
return "study.html";
}
// @PostMapping("/login")
// public String loginPost(@RequestParam String site, Model model){
// model.addAttribute("site", site);
//
// return "redirect:/"+site;
// }
@GetMapping("/signup")
public String signUp(
@RequestParam String site,
HttpServletRequest request
){
if(site == null) {
site = estimateSite(request.getParameter("referer"));
}
return "redirect:/"+site+"/signup";
}
@GetMapping("/access-denied")
public String accessDenied(){
return "/accessDenied";
}
}
권한별 Controller 따로 구현해 둔것은 Github 참고하기!