package com.jilongda.applet.config;
|
|
import com.jilongda.applet.security.AuthenticationProvider;
|
import com.jilongda.applet.security.SysUserDetailsService;
|
import com.jilongda.common.basic.Constant;
|
import com.jilongda.common.cache.CaffineCache;
|
import com.jilongda.common.redis.RedisAutoTemplate;
|
import com.jilongda.common.security.SecurityUtils;
|
import com.jilongda.common.security.filter.AuthenticationFilter;
|
import com.jilongda.common.security.hadler.SecurityAuthenticationEntryPoint;
|
import com.jilongda.common.swagger.SwaggerAutoConfiguration;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Configuration;
|
import org.springframework.http.HttpMethod;
|
import org.springframework.security.authentication.AuthenticationManager;
|
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
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.builders.WebSecurity;
|
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.crypto.password.PasswordEncoder;
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
|
/**
|
* 细粒度的访问控制
|
* <p>
|
* 注:需要使用注解@EnableGlobalMethodSecurity(prePostEnabled=true) 开启
|
*
|
* @author xiaochen
|
*/
|
@Configuration
|
@EnableWebSecurity
|
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
|
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
@Autowired
|
private SecurityAuthenticationEntryPoint securityAuthenticationEntryPoint;
|
@Autowired
|
private RedisAutoTemplate redisAutoTemplate;
|
@Autowired
|
private CaffineCache<String> accessTokenCache;
|
@Autowired
|
private CaffineCache<String> refreshTokenCache;
|
@Autowired
|
private PasswordEncoder passwordEncoder;
|
@Autowired
|
private SysUserDetailsService loadUserDetailsService;
|
|
|
/**
|
* 应用重启token无效,可手动使令牌无效,管理了token的生命周期
|
*
|
* @return
|
*/
|
@Bean
|
public SecurityUtils securityUtils() {
|
return new SecurityUtils(accessTokenCache, refreshTokenCache);
|
// return new SecurityUtils();
|
}
|
|
|
/**
|
* 不需要认证的在此处放行,比如系统的一些字典请求
|
* 会包含Basic认证的请求。意思是如果请求在Basic中存在,在此处也存在,那么该请求的认证会被忽略
|
* 这种方式的优势是不走 Spring Security 过滤器链
|
*
|
* @param web
|
*/
|
@Override
|
public void configure(WebSecurity web) {
|
web.ignoring().antMatchers(SwaggerAutoConfiguration.DOC_LIST);
|
web.ignoring().antMatchers(Constant.APPLET_AUTH_WHITELIST);
|
}
|
|
|
/**
|
* 使用自定义登录身份认证组件,自实现rest登录请求,不适用于在过滤其中实现 在过滤其中无法提供接口文档,维护不方便
|
*
|
* @param auth
|
*/
|
@Override
|
public void configure(AuthenticationManagerBuilder auth) {
|
auth.authenticationProvider(new AuthenticationProvider(loadUserDetailsService,passwordEncoder));
|
}
|
|
|
|
/**
|
* Security各项配置
|
*
|
* @param http
|
* @throws Exception
|
*/
|
@Override
|
protected void configure(HttpSecurity http) throws Exception {
|
// 需要Basic认证的请求
|
http
|
.cors().disable()
|
// 关闭登录,自定义接口实现
|
.formLogin().disable()
|
// 关闭httpBasic认证
|
.httpBasic().disable()
|
// 关闭退出,自定义接口实现
|
.logout().disable()
|
.csrf().disable()
|
// 放在 Cookie 中返回前端,防止跨域伪造
|
//.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and()
|
//.and()
|
.authorizeRequests()
|
// 跨域预检请求
|
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
|
// 登录URL permitAll() 无需保护 ---> 此种方式配置忽略认证规则会走Spring Security 过滤器链,在过滤器链中,给请求放行
|
// 不需要保护的请求,但需要经过过滤连
|
//.antMatchers(HttpMethod.POST, "/login").permitAll()
|
// 微信登录
|
.antMatchers(HttpMethod.GET, "/**/openId-by-jscode2session/**").permitAll()
|
.antMatchers(HttpMethod.POST, "/login").permitAll()
|
.antMatchers(HttpMethod.POST, "/code/login").permitAll()
|
.antMatchers(HttpMethod.POST, "/sendCode").permitAll()
|
.antMatchers(HttpMethod.POST, "/sendPassCode").permitAll()
|
.antMatchers(HttpMethod.POST, "/pageResetPassword").permitAll()
|
// 其他都需要权限认证
|
.anyRequest()
|
.authenticated()
|
// 其他所有请求需要身份认证
|
.and()
|
// 异常拦截
|
.exceptionHandling()
|
// 未授权用户访问无权限时的处理
|
.authenticationEntryPoint(securityAuthenticationEntryPoint);
|
// 此处存在session共享的问题,如要共享session,则需要管理
|
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
|
// 访问控制时登录状态检查过滤器
|
http.addFilterBefore(new AuthenticationFilter(securityUtils()), UsernamePasswordAuthenticationFilter.class);
|
// 异常捕捉过滤器,必须在AuthenticationFilter之前才能捕捉到异常信息
|
http.addFilterBefore(new AuthenticationFilter(securityUtils()), AuthenticationFilter.class);
|
//禁用缓存
|
http.headers().cacheControl();
|
}
|
|
|
/**
|
* 验证管理器,在登录接口时用到
|
*
|
* @return
|
* @throws Exception
|
*/
|
@Bean
|
@Override
|
public AuthenticationManager authenticationManager() throws Exception {
|
return super.authenticationManager();
|
}
|
|
}
|