Spring Security实现不同接口安全策略方法详解
1.前言
欢迎阅读SpringSecurity实战干货系列文章。最近有开发小伙伴提了一个有趣的问题。他正在做一个项目,涉及两种风格,一种是给小程序出接口,安全上使用无状态的JWTToken;另一种是管理后台使用的是Freemarker,也就是前后端不分离的Session机制。用SpringSecurity该怎么办?
2.解决方案
我们可以通过多次继承WebSecurityConfigurerAdapter构建多个HttpSecurity。HttpSecurity对象会告诉我们如何验证用户的身份,如何进行访问控制,采取的何种策略等等。
我们是这么配置的:
/**
*单策略配置
*
*@authorfelord.cn
*@seeorg.springframework.boot.autoconfigure.security.servlet.SpringBootWebSecurityConfiguration
*@since14:582019/10/15
*/
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled=true,jsr250Enabled=true,securedEnabled=true)
@EnableWebSecurity
@ConditionalOnClass(WebSecurityConfigurerAdapter.class)
@ConditionalOnWebApplication(type=ConditionalOnWebApplication.Type.SERVLET)
publicclassCustomSpringBootWebSecurityConfiguration{
/**
*ThetypeDefaultconfigureradapter.
*/
@Configuration
@Order(SecurityProperties.BASIC_AUTH_ORDER)
staticclassDefaultConfigurerAdapterextendsWebSecurityConfigurerAdapter{
@Override
protectedvoidconfigure(AuthenticationManagerBuilderauth)throwsException{
super.configure(auth);
}
@Override
publicvoidconfigure(WebSecurityweb){
super.configure(web);
}
@Override
protectedvoidconfigure(HttpSecurityhttp)throwsException{
//配置httpSecurity
}
}
}
上面的配置了一个HttpSecurity,我们如法炮制再增加一个WebSecurityConfigurerAdapter的子类来配置另一个HttpSecurity。伴随而来的还有不少的问题要解决。
2.1如何路由不同的安全配置
我们配置了两个HttpSecurity之后,程序如何让小程序接口和后台接口走对应的HttpSecurity?
HttpSecurity.antMatcher(StringantPattern)可以提供过滤机制。比如我们配置:
@Override
protectedvoidconfigure(HttpSecurityhttp)throwsException{
//配置httpSecurity
http.antMatcher("/admin/v1");
}
那么该HttpSecurity将只提供给以/admin/v1开头的所有URL。这要求我们针对不同的客户端指定统一的URL前缀。
举一反三只要HttpSecurity提供的功能都可以进行个性化定制。比如登录方式,角色体系等。
2.2如何指定默认的HttpSecurity
我们可以通过在WebSecurityConfigurerAdapter实现上使用@Order注解来指定优先级,数值越大优先级越低,没有@Order注解将优先级最低。
2.3如何配置不同的UserDetailsService
很多情况下我们希望普通用户和管理用户完全隔离,我们就需要多个UserDetailsService,你可以在下面的方法中对AuthenticationManagerBuilder进行具体的设置来配置UserDetailsService,同时也可以配置不同的密码策略。
@Override
protectedvoidconfigure(AuthenticationManagerBuilderauth)throwsException{
DaoAuthenticationProviderdaoAuthenticationProvider=newDaoAuthenticationProvider();
daoAuthenticationProvider.setUserDetailsService(newUserDetailsService(){
@Override
publicUserDetailsloadUserByUsername(Stringusername)throwsUsernameNotFoundException{
//自行实现
returnnull;
}
});
//也可以设计特定的密码策略
BCryptPasswordEncoderbCryptPasswordEncoder=newBCryptPasswordEncoder();
daoAuthenticationProvider.setPasswordEncoder(bCryptPasswordEncoder);
auth.authenticationProvider(daoAuthenticationProvider);
}
2.4最终的配置模板
上面的几个问题解决之后,我们基本上掌握了在一个应用中执行多种安全策略。配置模板如下:
/**
*多个策略配置
*
*@authorfelord.cn
*@seeorg.springframework.boot.autoconfigure.security.servlet.SpringBootWebSecurityConfiguration
*@since14:582019/10/15
*/
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled=true,jsr250Enabled=true,securedEnabled=true)
@EnableWebSecurity
@ConditionalOnClass(WebSecurityConfigurerAdapter.class)
@ConditionalOnWebApplication(type=ConditionalOnWebApplication.Type.SERVLET)
publicclassCustomSpringBootWebSecurityConfiguration{
/**
*后台接口安全策略.默认配置
*/
@Configuration
@Order(1)
staticclassAdminConfigurerAdapterextendsWebSecurityConfigurerAdapter{
@Override
protectedvoidconfigure(AuthenticationManagerBuilderauth)throwsException{
DaoAuthenticationProviderdaoAuthenticationProvider=newDaoAuthenticationProvider();
//用户详情服务个性化
daoAuthenticationProvider.setUserDetailsService(newUserDetailsService(){
@Override
publicUserDetailsloadUserByUsername(Stringusername)throwsUsernameNotFoundException{
//自行实现
returnnull;
}
});
//也可以设计特定的密码策略
BCryptPasswordEncoderbCryptPasswordEncoder=newBCryptPasswordEncoder();
daoAuthenticationProvider.setPasswordEncoder(bCryptPasswordEncoder);
auth.authenticationProvider(daoAuthenticationProvider);
}
@Override
publicvoidconfigure(WebSecurityweb){
super.configure(web);
}
@Override
protectedvoidconfigure(HttpSecurityhttp)throwsException{
//根据需求自行定制
http.antMatcher("/admin/v1")
.sessionManagement(Customizer.withDefaults())
.formLogin(Customizer.withDefaults());
}
}
/**
*app接口安全策略.没有{@linkOrder}注解优先级比上面低
*/
@Configuration
staticclassAppConfigurerAdapterextendsWebSecurityConfigurerAdapter{
@Override
protectedvoidconfigure(AuthenticationManagerBuilderauth)throwsException{
DaoAuthenticationProviderdaoAuthenticationProvider=newDaoAuthenticationProvider();
//用户详情服务个性化
daoAuthenticationProvider.setUserDetailsService(newUserDetailsService(){
@Override
publicUserDetailsloadUserByUsername(Stringusername)throwsUsernameNotFoundException{
//自行实现
returnnull;
}
});
//也可以设计特定的密码策略
BCryptPasswordEncoderbCryptPasswordEncoder=newBCryptPasswordEncoder();
daoAuthenticationProvider.setPasswordEncoder(bCryptPasswordEncoder);
auth.authenticationProvider(daoAuthenticationProvider);
}
@Override
publicvoidconfigure(WebSecurityweb){
super.configure(web);
}
@Override
protectedvoidconfigure(HttpSecurityhttp)throwsException{
//根据需求自行定制
http.antMatcher("/app/v1")
.sessionManagement(Customizer.withDefaults())
.formLogin(Customizer.withDefaults());
}
}
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。