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(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。