1,准备多个user,进行不同权限的演示
在重写UserDetailService中去修改不同的user,以此设置权限
2,configure(WebSecurity web)里配置了ignoring的资源,不受configure(HttpSecurity http)管理,尽量有依据
package org.springframework.security.config.annotation.web.configuration;
@Retention(RetentionPolicy.RUNTIME)
@Target({
ElementType.TYPE})
@Documented
@Import({
WebSecurityConfiguration.class, SpringWebMvcImportSelector.class, OAuth2ImportSelector.class, HttpSecurityConfiguration.class})
@EnableGlobalAuthentication
@Configuration
public @interface EnableWebSecurity {
boolean debug() default false;
}
debug作用
@Configuration
@EnableWebSecurity(debug = true)
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter
public void setFilterChainProxySecurityConfigurer(ObjectPostProcessor<Object> objectPostProcessor, @Value("#{@autowiredWebSecurityConfigurersIgnoreParents.getWebSecurityConfigurers()}") List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers) throws Exception {
this.webSecurity = (WebSecurity)objectPostProcessor.postProcess(new WebSecurity(objectPostProcessor));
if (this.debugEnabled != null) {
this.webSecurity.debug(this.debugEnabled);
}
webSecurityConfigurers.sort(WebSecurityConfiguration.AnnotationAwareOrderComparator.INSTANCE);
Integer previousOrder = null;
Object previousConfig = null;
Iterator var5;
SecurityConfigurer config;
for(var5 = webSecurityConfigurers.iterator(); var5.hasNext(); previousConfig = config) {
config = (SecurityConfigurer)var5.next();
Integer order = WebSecurityConfiguration.AnnotationAwareOrderComparator.lookupOrder(config);
if (previousOrder != null && previousOrder.equals(order)) {
throw new IllegalStateException("@Order on WebSecurityConfigurers must be unique. Order of " + order + " was already used on " + previousConfig + ", so it cannot be used on " + config + " too.");
}
previousOrder = order;
}
var5 = webSecurityConfigurers.iterator();
while(var5.hasNext()) {
//将配置的每一个securityConfigurer列表传递给webSecurity
config = (SecurityConfigurer)var5.next();
this.webSecurity.apply(config);
}
this.webSecurityConfigurers = webSecurityConfigurers;
}
@Bean(
name = {
"springSecurityFilterChain"}
)
public Filter springSecurityFilterChain() throws Exception {
boolean hasConfigurers = this.webSecurityConfigurers != null && !this.webSecurityConfigurers.isEmpty();
boolean hasFilterChain = !this.securityFilterChains.isEmpty();
Assert.state(!hasConfigurers || !hasFilterChain, "Found WebSecurityConfigurerAdapter as well as SecurityFilterChain. Please select just one.");
if (!hasConfigurers && !hasFilterChain) {
//如果没有配置,则取默认配置
WebSecurityConfigurerAdapter adapter = (WebSecurityConfigurerAdapter)this.objectObjectPostProcessor.postProcess(new WebSecurityConfigurerAdapter() {
});
this.webSecurity.apply(adapter);
}
Iterator var7 = this.securityFilterChains.iterator();
while(true) {
while(var7.hasNext()) {
SecurityFilterChain securityFilterChain = (SecurityFilterChain)var7.next();
this.webSecurity.addSecurityFilterChainBuilder(() -> {
return securityFilterChain;
});
Iterator var5 = securityFilterChain.getFilters().iterator();
while(var5.hasNext()) {
Filter filter = (Filter)var5.next();
if (filter instanceof FilterSecurityInterceptor) {
this.webSecurity.securityInterceptor((FilterSecurityInterceptor)filter);
break;
}
}
}
var7 = this.webSecurityCustomizers.iterator();
while(var7.hasNext()) {
WebSecurityCustomizer customizer = (WebSecurityCustomizer)var7.next();
customizer.customize(this.webSecurity);
}
//调用webSecurity的biud方法生成过滤器
return (Filter)this.webSecurity.build();
}
}
public final O build() throws Exception {
if (this.building.compareAndSet(false, true)) {
//TODO
this.object = this.doBuild();
return this.object;
} else {
throw new AlreadyBuiltException("This object has already been built");
}
}
protected final O doBuild() throws Exception {
synchronized(this.configurers) {
this.buildState = AbstractConfiguredSecurityBuilder.BuildState.INITIALIZING;
this.beforeInit();
//初始化,将所有httpSecurity注册到websecurity中
this.init();
this.buildState = AbstractConfiguredSecurityBuilder.BuildState.CONFIGURING;
this.beforeConfigure();
this.configure();
this.buildState = AbstractConfiguredSecurityBuilder.BuildState.BUILDING;
//websecurity的performBuild
O result = this.performBuild();
this.buildState = AbstractConfiguredSecurityBuilder.BuildState.BUILT;
return result;
}
}
protected Filter performBuild() throws Exception {
Assert.state(!this.securityFilterChainBuilders.isEmpty(), () -> {
return "At least one SecurityBuilder<? extends SecurityFilterChain> needs to be specified. Typically this is done by exposing a SecurityFilterChain bean or by adding a @Configuration that extends WebSecurityConfigurerAdapter. More advanced users can invoke " + WebSecurity.class.getSimpleName() + ".addSecurityFilterChainBuilder directly";
});
int chainSize = this.ignoredRequests.size() + this.securityFilterChainBuilders.size();
List<SecurityFilterChain> securityFilterChains = new ArrayList(chainSize);
Iterator var3 = this.ignoredRequests.iterator();
while(var3.hasNext()) {
RequestMatcher ignoredRequest = (RequestMatcher)var3.next();
securityFilterChains.add(new DefaultSecurityFilterChain(ignoredRequest, new Filter[0]));
}
var3 = this.securityFilterChainBuilders.iterator();
while(var3.hasNext()) {
SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder = (SecurityBuilder)var3.next();
/来自我们自己的配置
securityFilterChains.add(securityFilterChainBuilder.build());
}
FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);
if (this.httpFirewall != null) {
filterChainProxy.setFirewall(this.httpFirewall);
}
if (this.requestRejectedHandler != null) {
filterChainProxy.setRequestRejectedHandler(this.requestRejectedHandler);
}
filterChainProxy.afterPropertiesSet();
Filter result = filterChainProxy;
if (this.debugEnabled) {
this.logger.warn("\n\n********************************************************************\n********** Security debugging is enabled. *************\n********** This may include sensitive information. *************\n********** Do not use in a production system! *************\n********************************************************************\n\n");
result = new DebugFilter(filterChainProxy);
}
this.postBuildAction.run();
return (Filter)result;
}
3,loginProcessingUrl 和 TokenLoginFilter两种方式都可以配置登录以及实现token方案的演示
spring securiyt是由众多filters组合完成工作的,如果在loginProcessingUrl内去实现token的颁发,那就是要使用表单认证,我们需要自己自定义登录页面来处理我们的登录信息。
对此我们通常使用basic认证的方式
对于这两种方式的认证,简单来说
BASIC是利用HTTP头部进行认证,访问页面时会由浏览器弹框要求密码,这个是走HTTP协议层面的认证
FORM是基于页面,你需要自己实现一个登录页面,也就是示例中的/usercheck.jsp(名字你可以自己定),里面要有一个登录表单,表单的action和用户名 密码字段名都是框架定死的,然后你需要再实现一个servlet来处理这个表单的action,实现登录,实际上走的是session/cookie认证
4,login/logout的token持久化/清除方案
需要整合redis来做token的持久化处理,有效时长,刷新token以及token清除等,
扫描二维码关注公众号,回复: 13271949 查看本文章
5,SessionCreationPolicy.STATELESS的具体影响
security.sessions策略
6,把其它工程里关于SpringSecurity的功能,包括自定义注解等等,整合到single-security-jwt-model工程,形成一个专项工程。
找了spring security 的匿名注解的作用
7,TokenAuthenticationFilter对某些资源放行,跟Security configure里规则一致。
已做处理