암호화 해시는 PasswordEncoder를 DaoAuthenticationProvider로 설정하면 된다.
SecurityConfig.java
@Configuration@EnableWebSecuritypublicclassSecurityConfigextendsWebSecurityConfigurerAdapter{@AutowiredprivateUserDetailsServiceuserDetailsService;...@Overrideprotectedvoidconfigure(AuthenticationManagerBuilderauth)throwsException{// 사용자 세부 서비스를 설정하기 위한 오버라이딩이다.auth.userDetailsService(userDetailsService)// 로그인 관리// 프로바이더 하나 만들기.and().authenticationProvider(authenticationProvider());// Password Encoding 관리}// authenticationProvider()구현@BeanpublicAuthenticationProviderauthenticationProvider(){DaoAuthenticationProviderauthProvider=newDaoAuthenticationProvider();authProvider.setUserDetailsService(userDetailsService);// 주입된 UserDetailsService에 passwordEncoder를 설정한다.authProvider.setPasswordEncoder(passwordEncoder());returnauthProvider;}// passwordEncoder() 구현// 암호를 해시시키는 경우 BCryptPasswordEncoder를 사용한다. @BeanpublicPasswordEncoderpasswordEncoder(){returnnewBCryptPasswordEncoder();}}
BCryptPasswordEncoder 클래스를 살펴보면,
encode시 솔트를 사용하는 것을 볼 수 있다.
matches라는 메서드를 사용하여, 입력된 비밀번호와 DB에 저장된 값을 비교 할 수있다.
[2] service 에서 passwordEncoder 처리하기
회원가입 시 Dao를 가기위해 거쳐가는 Service의 joinUser메소드에서 passwordEncoder를 처리한다.
[1] 메소드 파라미터를 검사해 @AuthUser가 붙은 경우, 또 그 어노테이션이 붙은 파라미터의 타입이 SecurityUser인 경우 를 검사해야한다.
@OverridepublicbooleansupportsParameter(MethodParameterparameter){AuthUserauthUser=parameter.getParameterAnnotation(AuthUser.class);// @AuthUser가 안붙어있으면if(authUser==null){returnfalse;// 난 그 파라미터 관심없어 return false!}// @AuthUser는 붙어있는데 SecurityUser가 아니면 return false!if(parameter.getParameterType().equals(SecurityUser.class)==false){//클래스 객체 비교returnfalse;}returntrue;}
[2] 위의 supportsParameter메소드를 통과하면 resolveArgument 메소드에서 처리할 수 있다.
@OverridepublicObjectresolveArgument(MethodParameterparameter,ModelAndViewContainermavContainer,NativeWebRequestwebRequest,WebDataBinderFactorybinderFactory)throwsException{Objectprincipal=null;// SecurityContextHolder에서 갖고있는 인증 정보를 확인한다.Authenticationauthentication=SecurityContextHolder.getContext().getAuthentication();// 인증 정보가 없는 경우 인증 정보 등록if(authentication!=null){principal=authentication.getPrincipal();}// 인증 정보가 없다면 return nullif(principal==null||principal.getClass()==String.class){returnnull;}returnprincipal;}
[3] 인증을 필요로하는 메소드 파라미터 수정
회원정보 수정을 해야하는 경우, 회원이 로그인상태(인증상태)이여야 하고, 해당 회원의 회원 정보만 수정할 수 있어야 한다. 이제 @AuthUser 어노테이션을 통해 인증정보를 확인 할 수 있다.
SecurityUser는 회원 정보를 저장하는 역할이다. (UserDetails를 구현한 클래스)
SecurityUser.java의 기존 field
privateStringname;// biz dataprivateCollection<?extendsGrantedAuthority>authorities;privateStringusername;privateStringpassword;
no filed 추가 후 getter, setter 추가
// domain fields(principal: 보호할 사용자 중요 데이터)privateLongno;privateStringname;// biz data// security fieldsprivateCollection<?extendsGrantedAuthority>authorities;privateStringusername;// credential(email)privateStringpassword;// credential...publicLonggetNo(){returnno;}publicvoidsetNo(Longno){this.no=no;}...
인증을 위한 security fields와, 회원의 중요 데이터 domain fields 가 있다.