前言:
现在小伙伴们对“springsecurity配置解析”可能比较关心,各位老铁们都需要学习一些“springsecurity配置解析”的相关文章。那么小编在网络上网罗了一些有关“springsecurity配置解析””的相关知识,希望朋友们能喜欢,各位老铁们快快来了解一下吧!为了提高开发效率,现在的项目基本采用springboot的方式开发,本文主要采用SpringBoot方式配置SpringSecurity,然后结合传统的xml配置方式进行比较说明,本文主要讲如何配置,具体类的代码实现会另讲
自定义配置入口
自定义配置需要继承 WebSecurityConfigurerAdapter 进行配置,重写 configure(HttpSecurity http) 方法
springboot写法
@Overrideprotected void configure(HttpSecurity http) throws Exception { //步骤1: 允许 "/setAuth", "/api/**" 无需要权限访问http.authorizeRequests().antMatchers("/setAuth", "/api/**").permitAll().and() .authorizeRequests() // 自定义安全过来拦截 .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() { @Override public <O extends FilterSecurityInterceptor> O postProcess(O fsi) { //步骤2:配置访问决策 fsi.setAccessDecisionManager(accessDecisionManager()); //步骤3:配置权限数据源 fsi.setSecurityMetadataSource(mySecurityMetadataSource()); fsi.setRejectPublicInvocations(true); return fsi; } }).and().formLogin().and().httpBasic() ; // 禁用CSRF http.csrf().disable(); //步骤4:配置登录处理入口 http.exceptionHandling().authenticationEntryPoint(new MyLoginUrlAuthenticationEntryPoint()) //步骤5:配置访问拒绝处理 .accessDeniedHandler(new MyAccessDeniedHandler()) //步骤6:配置退出访问地址 .and().logout().logoutUrl("/logout") //步骤7:配置退出跳转地址 .logoutSuccessUrl("/loginAjax"); // 步骤8:配置登录成功处理 http.formLogin().successHandler(authenticationSuccessHandler()); // 步骤9:配置登录失败处理 http.formLogin().failureHandler(authenticationFailureHandler()); }
xml写法
<!-- 允许 "/setAuth", "/api/**" 无需要权限访问 --><http pattern="/setAuth" security="none"/><http pattern="/api/**" security="none"/><http auto-config="true" entry-point-ref="myLoginUrlAuthenticationEntryPoint"> <!-- 访问拒绝处理 --> <access-denied-handler ref="accessDeniedHandler" /> <!--form登录 login-page: 登录访问地址 authentication-failure-url:认证失败跳转地址 authentication-success-handler-ref: 认证成功处理类 --> <form-login login-page="${security.loginFormUrl}" authentication-failure-url="${security.loginFormUrl}?login_error=1" authentication-success-handler-ref="httpAuthenticationSuccessHandler" default-target-url="${security.defaultTargetUrl}" always-use-default-target="false" /> <!-- 退出成功跳转地址 --> <logout logout-success-url="${security.loginFormUrl}"/> <http-basic /> <!-- 自定义安全过来拦截 --> <custom-filter before="FILTER_SECURITY_INTERCEPTOR" ref="filterSecurityInterceptor"/> </http>访问决策配置
自定义访问决策实现AccessDecisionManager接口,通过登录用户具备的权限和访问资源需要的权限进行比较决策
springboot写法
public AccessDecisionManager accessDecisionManager() { return new AccessDecisionManager();}
xml写法
<beans:bean id="accessDecisionManager" class="com.vstore.boot.autoconfigure.security.AccessDecisionManager"/>权限元数据来源配置
自定义权限元数据来源实现 FilterInvocationSecurityMetadataSource 接口,关键重写public Collection<ConfigAttribute> getAttributes(Object object) 方法,该方法返回访问资源所需要的权限
springboot写法
public MySecurityMetadataSource mySecurityMetadataSource() { return new MySecurityMetadataSource(dataSource,securityProperties.getLoadAllResourceQuery()); }
MySecurityMetadataSource 第一参数是数据源,第二参数是一个查询sql语句,根据表结构SQL语句是下面这样的,查询出资源和权限对应列表
select resource_url as url,permission_code code from sys_permission p left join sys_permission_resource pr on p.id=pr.permission_id left join sys_resource r on r.id=pr.resource_id where resource_url is not null
resource_url是请求资源,permission_code是资源对应权限,MySecurityMetadataSource 中的getAttributes(Object object) 方法返回资源所需要的权限。
xml写法
<beans:bean id="invocationSecurityMetadataSourceService" class="com.vstore.boot.autoconfigure.security.MySecurityMetadataSource"> <beans:constructor-arg index="0"> <beans:ref bean="dataSource" /> </beans:constructor-arg> <beans:constructor-arg index="1"> <beans:value>${security.loadAllResourceQuery}</beans:value> </beans:constructor-arg> </beans:bean>登录入口配置
由于项目是一个前后端分离的项目,这边实现 AuthenticationEntryPoint 接口,返回一个json格式,前端通过json解析跳转到登录页面
public class MyLoginUrlAuthenticationEntryPoint implements AuthenticationEntryPoint { @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { response.setCharacterEncoding("utf-8"); response.setContentType("text/javascript;charset=utf-8"); Response<String> responseMsg=new Response<>(); responseMsg.setResult("没有登录"); responseMsg.setResCode(403); response.getWriter().print(JsonUtils.convert2String(responseMsg) ); }}登录成功和失败处理
登录成功和失败都会有相应的接口,成功的接口:AuthenticationSuccessHandler ,失败的接口:AuthenticationFailureHandler,实现对应的接口,在配置指定对应实现类即可。
举例:登录失败配置指定
// 步骤9:配置登录失败处理http.formLogin().failureHandler(authenticationFailureHandler());
authenticationFailureHandler()实现
public AuthenticationFailureHandler authenticationFailureHandler(){ return new AuthenticationFailureHandler() { @Override public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { response.setCharacterEncoding("utf-8"); response.setContentType("text/javascript;charset=utf-8"); Response<String> responseMsg=new Response<>(); responseMsg.setResult(exception.getMessage()); responseMsg.setResCode(403); response.getWriter().print(JsonUtils.convert2String(responseMsg) ); } }; }