package com.jkcredit.invoice.hub.config; import org.springframework.beans.factory.BeanInitializationException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.authentication.configuration.EnableGlobalAuthentication; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 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.config.http.SessionCreationPolicy; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.web.filter.CorsFilter; import org.zalando.problem.spring.web.advice.security.SecurityProblemSupport; import javax.annotation.PostConstruct; /** * @description: * @author: xusonglin * @create: 2020/1/3 10:14 * @version: V1.0 **/ @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) @Import(SecurityProblemSupport.class) public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Autowired AjaxAuthenticationEntryPoint authenticationEntryPoint; // 未登陆时返回 JSON 格式的数据给前端(否则为 html) @Autowired AjaxAuthenticationSuccessHandler authenticationSuccessHandler; // 登录成功返回的 JSON 格式数据给前端(否则为 html) @Autowired AjaxAuthenticationFailureHandler authenticationFailureHandler; // 登录失败返回的 JSON 格式数据给前端(否则为 html) @Autowired AjaxLogoutSuccessHandler logoutSuccessHandler; // 注销成功返回的 JSON 格式数据给前端(否则为 登录时的 html) @Autowired AjaxAccessDeniedHandler accessDeniedHandler; // 无权访问返回的 JSON 格式数据给前端(否则为 403 html 页面) @Autowired JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter; // JWT 拦截器 private final UserDetailsService userDetailsService; private final AuthenticationManagerBuilder authenticationManagerBuilder; private final AuthenticationEntryPointHandler authenticationEntryPointHandler; private final CorsFilter corsFilter; public SecurityConfiguration(UserDetailsService userDetailsService, AuthenticationManagerBuilder authenticationManagerBuilder, AuthenticationEntryPointHandler authenticationEntryPointHandler, CorsFilter corsFilter) { this.userDetailsService = userDetailsService; this.authenticationManagerBuilder = authenticationManagerBuilder; this.authenticationEntryPointHandler = authenticationEntryPointHandler; this.corsFilter = corsFilter; } @PostConstruct public void init() { try { authenticationManagerBuilder .userDetailsService(userDetailsService) .passwordEncoder(passwordEncoder()); } catch (Exception e) { throw new BeanInitializationException("Security configuration failed", e); } } @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } // 此处需要使用@Bean引入,作用不是为了上面方法中使用 // 作用在于使用@Bean将PasswordEncoder作为Bean引入 // 同时此方法也可以指定加密方式 @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Override protected void configure(HttpSecurity http) throws Exception { // 去掉 CSRF http.csrf().disable() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 使用 JWT,关闭token .and() .httpBasic().authenticationEntryPoint(authenticationEntryPoint) .and() .authorizeRequests() .antMatchers("/api/**").permitAll() .anyRequest() .access("@rbacauthorityservice.hasPermission(request,authentication)") // RBAC 动态 url 认证 .and() .formLogin() //开启登录 .successHandler(authenticationSuccessHandler) // 登录成功 .failureHandler(authenticationFailureHandler) // 登录失败 .permitAll() .and() .logout() .logoutSuccessHandler(logoutSuccessHandler) .permitAll(); // 记住我 http.rememberMe().rememberMeParameter("remember-me") .userDetailsService(userDetailsService).tokenValiditySeconds(3600); http.exceptionHandling().accessDeniedHandler(accessDeniedHandler); // 无权访问 JSON 格式的数据 http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); // JWT Filter } // @Override // protected void configure(HttpSecurity http) throws Exception { // http // .exceptionHandling() // .authenticationEntryPoint(authenticationEntryPointHandler) // .and() // .csrf().disable()//禁用了 csrf 功能 // .authorizeRequests()//限定签名成功的请求 // .antMatchers("/api/**").permitAll()//不拦截 oauth 开放的资源 // .anyRequest().authenticated()// 其他请求进行拦截 // .and() // .formLogin() // .loginProcessingUrl("/login")//使用 spring security 默认登录页面 // .successHandler(customAuthenticationSuccess) // .failureHandler(customAuthenticationFailure) // .permitAll() // .and() // .logout() // .logoutUrl("/logout") // .permitAll(); // } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth .userDetailsService(userDetailsService) .passwordEncoder(passwordEncoder()); } }