프로젝트 아키텍처 : 봄 봄 - 보안 - 부팅 + + Thymeleaf
1. 리드 팩 ( 부팅 하고 자신의 패키지 버전 번호를 가져 thymeleaf, 나는 훈제 속성 )
< 의존성 > < 의 groupId > org.springframework.security </ 의 groupId > < artifactId를 > 스프링 보안 검사 </ artifactId를 > < 범위 > 시험 </ 범위 > </ 의존성 > < 의존성 > < 의 groupId > org.springframework.boot </ 의 groupId > < artifactId를 > 스프링 부팅 스타터 보안 </ artifactId를 > </ 의존성>
2. 핵심 구성 클래스 (마지막 릴리스의 전체 코드)
2.1 사용자 정의 보안 구성 클래스는,이 추상 클래스 WebSecurityConfigurerAdapter 상속합니다.
2.2 표시된 @EnableWebSecurity의 @EnableGlobalMethodSecurity (prePostEnabled = true로) 두 노트
2.3 재 작성 구성 (HttpSecurity HTTP) 방법, 구성 설정 http.formLogin () 메소드를 사용하여 체인 프로그래밍을 사용하여 당신이 필요로하는 (절편 매개 변수 등 경로, 크로스 도메인 요청을 로그)
2.4 재 작성 구성 (WebSecurity 웹) 메소드, 정적 리소스의 해제
web.ignoring (). antMatchers ( "/ ** / *. JS", "/**/*.css", "/**/*.png", "/**/*.jpg", "/ . ** / * GIF ","/**/*.map ");
2.5 재 작성 구성 (AuthenticationManagerBuilder의 인증) 방법, 로그인 검증을 사용자 정의
loginAuthenticationProvider : 이것은 사용자 정의 로그인 검증 클래스는 전화로,이다
customUserDetailsService : 이것은 사용자 계정 스토리지 클래스는 호출에있다
customPasswordEncoder은 :이 주사를 호출, 비밀번호 암호화 클래스 정의입니다
loginAuthenticationProvider.setUserDetailsService (customUserDetailsService); loginAuthenticationProvider.setPasswordEncoder (customPasswordEncoder); auth.authenticationProvider (loginAuthenticationProvider); 슈퍼 .configure (인증);
3.security 국제 문제
보안 프로세스로,이 클래스 DaoAuthenticationProvider가의 additionalAuthenticationChecks의 네이티브 코드 방식 때문에
반환에서 당신은 때 전면 방문 페이지 실패 잘못된 자격 증명 뉴스. 이 시스템이 친절 보이지 않는됩니다.
이 솔루션은 다음과 같습니다
1. 자원 폴더에 messages_zh_CN.properties이 파일을 추가합니다. 반환 할 경우 전면을 사용자 정의합니다.
2. 사용자 정의 로그인 검증 클래스 loginAuthenticationProvider (마지막 릴리스 전체 코드)
3. 사용자 지정 수준의 보안 구성에 따라 구성
전체 코드 :
1. 사용자 정의 보안 구성 클래스
@EnableWebSecurity @EnableGlobalMethodSecurity (prePostEnabled = True로 ) 공용 클래스 SecurityConfiguration는 연장 WebSecurityConfigurerAdapter { 개인 최종 CustomPasswordEncoder customPasswordEncoder 단계; 민간 최종 CustomUserDetailsService customUserDetailsService; 민간 최종 CommonProperties의 commonProperties; @Autowired 공개 SecurityConfiguration (CustomPasswordEncoder customPasswordEncoder, CustomUserDetailsService customUserDetailsService, CommonProperties commonProperties) { 이 .customPasswordEncoder =customPasswordEncoder; 이 .customUserDetailsService = customUserDetailsService; 이 .commonProperties = 용의 commonProperties; } @Autowired 개인 LoginAuthenticationProvider의 loginAuthenticationProvider을; / ** * HTTP配置 * @param HTTP * @throws 예외 * / @Override가 보호 무효 구성을 (HttpSecurity HTTP)가 발생 예외 { http.formLogin () .loginPage ( "/ 로그인" ) .loginProcessingUrl을 ( "/ doLogin" ) // 당신은 로그인 페이지와 성공적인 점프 페이지를 지정한 후 .successForwardUrl ( "/ loadIndex" ) 수다 좋은 (). authorizeRequests () .antMatchers (commonProperties.getAllowList ()) // 모든 사용자의 URL을 위 접근 (로그인하지 않고) .permitAll () .AND () .authorizeRequests ()를 .anyRequest () // 위 이외에 로그인해야합니다 (.authenticated) .AND () () .logout // 지정된 로그 아웃 URL .logoutUrl ( "/ doLogout" ) .invalidateHttpSession ( true로 /**/*.png ","/**/*.jpg ","/**/*.gif ","/**/*.map "); ) .AND () .headers () .frameOptions () // 프레임 프레임 .sameOrigin () // CSRF 크로스 도메인 보호 재정의 특별한 URL의 .AND () CSRF () ignoringAntMatchers (commonProperties.getAllowList ()); ... } / * * * 정적 자원 해제 *의 파라미터 : 웹 * / @Override 공공 무효 구성 (WebSecurity 웹) { // 정적 자원 필터 web.ignoring (). antMatchers ( "/ ** / *. JS", "/ ** / * .CSS ","/**/*.png "," * 사용자 정의 인증 방법 * } / ** @Bean파라미터 : 인증의 *는 @throws 예외 * / @Override은 보호 공간 (AuthenticationManagerBuilder 승인에) 구성을 발생 예외 { loginAuthenticationProvider.setUserDetailsService (customUserDetailsService)를; loginAuthenticationProvider.setPasswordEncoder (customPasswordEncoder); auth.authenticationProvider (loginAuthenticationProvider); 슈퍼 .configure (인증); } / ** *自定义认证管理类 * @return * @throws 예외 * / @Override의 공공AuthenticationManager에 authenticationManagerBean는 () 가 발생 예외 { 반환 슈퍼 (.authenticationManagerBean를); } / ** *自定义密码加密类 * @return * / @Bean 공개 되는 PasswordEncoder되는 PasswordEncoder () { 반환 PasswordEncoderFactories.createDelegatingPasswordEncoder을 (); } }
2. 사용자 계정 저장소 클래스
@Service 공공 클래스 CustomUserDetailsService는 구현 UserDetailsService의 { 민간 최종 AuthTokenService authTokenService을; 개인 이력 로그 = LoggerFactory.getLogger ( 이 .getClass ()); @Autowired 공개 CustomUserDetailsService (AuthTokenService authTokenService) { 이 .authTokenService = authTokenService; } / ** *将用户详细信息放入보안 세션中 * 파라미터 : 사용자 이름 * @return * / @Override의 공공LoadUserByUsername 된 UserDetails (문자열 사용자 이름) { 은 try은 { Assert.IsTrue (StringUtils.isNotBlank (사용자 이름), "사용자 또는 암호를 다시 입력하십시오 올바르지 않습니다" ) // 허가가 구성되어 사용자 이름으로 사용자 정보를 얻을 객체 인 UserDTO 사용자 정보 = authTokenService.getUserDetail (사용자 이름) ResourceBO 자원 = userInfo.getResource (); 목록 <으로 GrantedAuthority> 당국 = 새로운 새로운 ArrayList를 <으로 GrantedAuthority> (); IF (자원! = null이 ) { buildAuth (자원, 기관); } 반환 새 새UserBO (사용자 정보, 기관); } 캐치 (는 IllegalArgumentException E) { 던져 새로운 새로운 UsernameNotFoundException ( "다시 입력하세요 사용자 또는 암호" ); } 캐치 (예외 E) { log.error ( "사용자 정보 이상 획득" , E) ; 던져 새로운 새로운 UsernameNotFoundException ( "사용자 또는 암호를 다시 입력하십시오" ); } } }
3. 사용자 정의 암호 암호화 클래스
@Service 공공 클래스 CustomPasswordEncoder가 구현 되는 PasswordEncoder { @Override 공공 문자열 인코딩 (의 CharSequence의 CharSequence가) { 반환 charSequence.toString를 (); } @Override 공공 부울 일치 (CharSequence를 CharSequence를, 문자열들) { 반환 에 대해서는 s.equals (인코딩 (CharSequence를)); } }
4. 사용자 보안 인증 클래스
@Component 공공 클래스 LoginAuthenticationProvider는 확장 DaoAuthenticationProvider는 { @Autowired 개인 CustomUserDetailsService customUserDetailsService을; @Autowired 개인 CustomPasswordEncoder의 customPasswordEncoder을; @Autowired 전용 공간 setJdbcUserDetailsService () { setUserDetailsService (customUserDetailsService); } / ** *自定义보안国际化 * / @PostConstruct 공공 무효 initProvider () { ReloadableResourceBundleMessageSource localMessageSource = 새ReloadableResourceBundleMessageSource (); localMessageSource.setBasenames ( "messages_zh_CN" ); 메시지 = 새로운 MessageSourceAccessor (localMessageSource); } / ** *复写认证失败方法 * @param 용 의 UserDetails * @param의 인증 *는 @throws 있는 AuthenticationException * / @Override가 보호 공간 additionalAuthenticationChecks (인 UserDetails 된 UserDetails, UsernamePasswordAuthenticationToken를 인증)이 발생 있는 AuthenticationException을 { 만약(authentication.getCredentials () == null이 ) { logger.debug는 ( "인증 실패 : 자격 증명이 제공되지" ); 던져 새로운 BadCredentialsException을 (messages.getMessage ( "AbstractUserDetailsAuthenticationProvider.badCredentials", "잘못된 자격 증명" )); } 문자열 presentedPassword = authentication.getCredentials의 toString ()을 ().; 만약 (! customPasswordEncoder.matches (presentedPassword, userDetails.getPassword ())) { logger.debug는 ( "인증에 실패했습니다 : 비밀번호 저장 값과 일치하지 않습니다" ); 던져 새로운BadCredentialsException (messages.getMessage ( "AbstractUserDetailsAuthenticationProvider.badCredentials", "잘못된 자격 증명" )); } } }