UserDetailService의 interface를 imlpement 한거임.
package com.example.service;
import java.util.Collection;
import com.example.dto.MemberDTO;
import com.example.mapper.MemberMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
@Service
public class MemberDetailServiceImpl implements UserDetailsService {
@Autowired
MemberMapper mMapper;
// 로그인에서 입력하는 정보중에서 아이디를 받음
// MemberMapper를 이용해서 정보를 가져와서 UserDetails
// userdetailservice에서 미리 설계가 되어 있음.
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
System.out.println("username" + username);
MemberDTO member = mMapper.memberEmail(username);
System.out.println("--------------------------" + member);
// 권한 정보를 문자열 배열로 만듦.
String[] strRole = { member.getUrole() };
// String 배열 권한을 collection<Granted ...> 타입으로 변환함
Collection<GrantedAuthority> role = AuthorityUtils.createAuthorityList(strRole);
// 권한을 여러개 줄 수 있다 customer, seller, admin 이렇게
// 아이디, 암호, 권한들 ...
User user = new User(member.getUemail(), member.getUpw(), role);
// 암호화를 했기 때문에 안 됨.
return user;
}
}
리턴타입이 메일, 패스워드, 권한을 담아야함.
권한은 여러개를 담을 수 있음.
package com.example.config;
import com.example.service.MemberDetailServiceImpl;
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.crypto.bcrypt.BCryptPasswordEncoder;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// 1. 직접 만든 detailService 객체 가져오기
@Autowired
MemberDetailServiceImpl mService;
// 2. 암호화 방법 객체 생성 @Bean은 서버 구동시 자동으로 객체 생성됨
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
// 3. 직접만든 dtailsService에 암호화 방법 적용
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(mService)
.passwordEncoder(bCryptPasswordEncoder());
}
AuthenticationManagerBuilder는 HttpSecurity에 포함된 거임.
아래에서 HttpSecurity http를 통해서 위에서 담은걸 쓰는거임
// 기존기능을 제거한 후 필요한 것을 추가
@Override
protected void configure(HttpSecurity http) throws Exception {
// 페이지별 접근권한 설정
http.authorizeRequests()
.antMatchers("/security_admin", "/security_admin/**")
.hasAnyAuthority("ADMIN")
.antMatchers("/security_seller", "/security_seller/**")
.hasAnyAuthority("ADMIN", "SELLER")
.antMatchers("/security_customer", "/security_customer/**")
.hasAnyAuthority("CUSTOMER")
.anyRequest().permitAll();
// 로그인 페이지 설정, 단 post는 직접 만들지 않음.
http.formLogin()
.loginPage("/member/security_login")
.loginProcessingUrl("/member/security_loginaction")
.usernameParameter("uemail")
.passwordParameter("upw")
.defaultSuccessUrl("/security_home", true)
.permitAll();
// 로그아웃 페이지 설정, url에 맞게 post로 호출하면 딤
http.logout()
.logoutUrl("/member/security_logout")
.logoutSuccessUrl("/security_home")
.invalidateHttpSession(true)
.clearAuthentication(true)
.permitAll();
// 접근권한불가 403
http.exceptionHandling().accessDeniedPage("/security_403");
// super.configure(http);
// super가 부모의 기능이다.
// 이걸 뺴버리면 부모기능을 안쓰겠다.
// h2 console db사용을 위해서 임시로
// 나중에 빼야함. 보안을 위해
http.csrf().disable();
http.headers().frameOptions().sameOrigin();
}
// extends가 안되는 상황에서 securityconfig에 컨트롤 .을 써서 불렀음
}
antMatchers("/login**", "/web-resources/**", "/actuator/**")
특정 리소스에 대해서 권한을 설정합니다.
antMatchers("/login**", "/web-resources/**", "/actuator/**").permitAll()
antMatchers 설정한 리소스의 접근을 인증절차 없이 허용한다는 의미 입니다.
antMatchers("/admin/**").hasAnyRole("ADMIN")
리소스 admin으로 시작하는 모든 URL은 인증후 ADMIN 레벨의 권한을 가진 사용자만 접근을 허용한다는 의미입니다.
anyRequest().authenticated()
모든 리소스를 의미하며 접근허용 리소스 및 인증후 특정 레벨의 권한을 가진 사용자만 접근가능한 리소스를 설정하고 그외 나머지 리소스들은 무조건 인증을 완료해야 접근이 가능하다는 의미입니다.
http.formLogin();
로그인 페이지와 기타 로그인 처리 및 성공 실패 처리를 사용하겠다는 의미 입니다.
loginPage("/login-page")
사용자가 따로 만든 로그인 페이지를 사용하려고 할때 설정합니다.
따로 설정하지 않으면 디폴트 URL이 “/login”이기 때문에 “/login”로 호출하면 스프링이 제공하는 기본 로그인페이지가 호출됩니다.
loginProcessingUrl("/login-process")
로그인 즉 인증 처리를 하는 URL을 설정합니다. “/login-process” 가 호출되면 인증처리를 수행하는 필터가 호출됩니다.
defaultSuccessUrl("/main")
정상적으로 인증성공 했을 경우 이동하는 페이지를 설정합니다.
설정하지 않는경우 디폴트값은 “/” 입니다.