/* * Copyright (c) 2020 yifu4cloud Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.yifu.cloud.plus.v1.yifu.auth.config; import com.fasterxml.jackson.databind.ObjectMapper; import com.yifu.cloud.plus.v1.yifu.auth.filter.PasswordDecoderFilter; import com.yifu.cloud.plus.v1.yifu.auth.handler.YifuAuthenticationFailureHandlerImpl; import com.yifu.cloud.plus.v1.yifu.auth.handler.YifuClientLoginSuccessHandler; import com.yifu.cloud.plus.v1.yifu.common.security.component.YifuDaoAuthenticationProvider; import com.yifu.cloud.plus.v1.yifu.common.security.grant.CustomAppAuthenticationProvider; import com.yifu.cloud.plus.v1.yifu.common.security.handler.FormAuthenticationFailureHandler; import com.yifu.cloud.plus.v1.yifu.common.security.handler.SsoLogoutSuccessHandler; import lombok.RequiredArgsConstructor; import lombok.SneakyThrows; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.CacheManager; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Primary; import org.springframework.core.annotation.Order; import org.springframework.security.authentication.AuthenticationManager; 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.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.factory.PasswordEncoderFactories; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.security.web.authentication.AuthenticationFailureHandler; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; /** * @author lengleng * @date 2022/1/12 认证相关配置 */ @Log4j2 @Primary @Order(90) @Configuration @RequiredArgsConstructor public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter { @Autowired private ObjectMapper objectMapper; @Autowired private ClientDetailsService clientDetailsService; @Lazy @Autowired private AuthorizationServerTokenServices defaultAuthorizationServerTokenServices; @Autowired private CacheManager cacheManager; @Autowired private TokenStore tokenStore; @Override @SneakyThrows protected void configure(HttpSecurity http) { http.addFilterBefore(getPasswordDecoderFilter(),PasswordDecoderFilter.class) .formLogin().loginPage("/token/login").loginProcessingUrl("/token/form") .failureHandler(authenticationFailureHandler()).and().logout() .logoutSuccessHandler(logoutSuccessHandler()).deleteCookies("JSESSIONID").invalidateHttpSession(true) .and() .authorizeRequests().antMatchers("/**/login","/token/**", "/actuator/**", "/mobile/**", "/oauth/token").permitAll() .anyRequest().authenticated().and().csrf().disable(); } /** * 自定义 provider 列表注入 * @param auth AuthenticationManagerBuilder */ @Override protected void configure(AuthenticationManagerBuilder auth) { YifuDaoAuthenticationProvider daoAuthenticationProvider = new YifuDaoAuthenticationProvider(); daoAuthenticationProvider.setPasswordEncoder(passwordEncoder()); // 处理默认的密码模式认证 auth.authenticationProvider(daoAuthenticationProvider); // 自定义的认证模式 auth.authenticationProvider(new CustomAppAuthenticationProvider()); } @Bean @Override @SneakyThrows public AuthenticationManager authenticationManagerBean() { return super.authenticationManagerBean(); } /** * 认证中心静态资源处理 * @param web WebSecurity */ @Override public void configure(WebSecurity web) { web.ignoring().antMatchers("/css/**", "/error"); } /** * sso 表单登录失败处理 * @return FormAuthenticationFailureHandler */ @Bean public AuthenticationFailureHandler authenticationFailureHandler() { return new FormAuthenticationFailureHandler(); } /** * SSO 退出逻辑处理 * @return LogoutSuccessHandler */ @Bean public LogoutSuccessHandler logoutSuccessHandler() { return new SsoLogoutSuccessHandler(); } /** * 密码处理器 * @return 动态密码处理器 {类型}密文 */ @Bean public PasswordEncoder passwordEncoder() { return PasswordEncoderFactories.createDelegatingPasswordEncoder(); } /** * @author fxj * @date 2022/5/27 17:22 */ public PasswordDecoderFilter getPasswordDecoderFilter(){ PasswordDecoderFilter filter = new PasswordDecoderFilter(); try { filter.setAuthenticationManager(this.authenticationManager()); }catch (Exception e){ log.error("WebSecurityConfigure>>>>>",e); } filter.setAuthenticationSuccessHandler(yifuClientLoginSuccessHandler()); filter.setAuthenticationFailureHandler(yifuAuthenticationFailureHandler()); return filter; } private AuthenticationFailureHandler yifuAuthenticationFailureHandler() { return YifuAuthenticationFailureHandlerImpl.builder() .objectMapper(objectMapper).build(); } private AuthenticationSuccessHandler yifuClientLoginSuccessHandler() { return YifuClientLoginSuccessHandler.builder() .objectMapper(objectMapper) .clientDetailsService(clientDetailsService) .passwordEncoder(passwordEncoder()) .cacheManager(cacheManager) .tokenStore(tokenStore) .defaultAuthorizationServerTokenServices(defaultAuthorizationServerTokenServices).build(); } }