生活加油:摘一句子:
“我希望自己能写这样的诗。我希望自己也是一颗星星。如果我会发光,就不必害怕黑暗。如果我自己是那么美好,那么一切恐惧就可以烟消云散。于是我开始存下了一点希望—如果我能做到,那么我就战胜了寂寞的命运。”
-----------------------------王小波《我在荒岛上迎接黎明》
————————————————
嗯,刚学的时候,一大堆,明白是配置了啥,不知道为啥那么配,嗯,今天把配置思想和小伙伴分享,是很简单的那种,不足之处请留言.
SpringSecurity的配置基于WebSecurityConfigurerAdapter的实现类,我们这里主要讲基本配置,即configure(HttpSecurity http)方法的配置,其实大都有默认值,我们可以直接用默认值,也可以自己设置.
私以为简单配置三点:
认证(SpringSecurity在第一次登录做认证,这时候只进行认证,不进行授权(鉴权处理))
表单认证:涉及到的配置包括前端登录请求的url,登录失败,登录成功返回的页面url,已及表单返回字段的用户名密码K的设置,还有登陆成功回调处理和登录失败回调处理.这里要注意登录数据是通过key/value的形式来传递.
自定义认证,(验证码):自定义验证采用,在自定义过滤器的方式,在最开始插入一个过滤器链,需要自定义异常,自定义失败登录失败处理器,注意这里的失败处理器要和表单登录使用同一个失败处理器.
授权(基于RBAC权限控制):
授权这样分析基于RBAC的权限控制,即用户分配角色,角色分配权限.需要配置根据访问路径得到需要的角色的处理类(FilterlnvocationSecurityrMetadataSource),根据返回角色进行鉴权处理类(AccessDecisionManager) , 同时判断是否登录,还需要配置认证失败的处理器.
注销登录
注销登录默认的url为"/logout".需要配置,注销登录处理器
配置图:
SpringSecurity简单配置图:
下面就上面讲的代码分析
一.认证:
1.configure(HttpSecurity http)方法的配置:
package com.liruilong.hros.config; import com.fasterxml.jackson.databind.ObjectMapper; import com.liruilong.hros.filter.VerifyCodeFilter; import com.liruilong.hros.model.Hr; import com.liruilong.hros.model.RespBean; import com.liruilong.hros.service.HrService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.*; import org.springframework.security.config.annotation.ObjectPostProcessor; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 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.WebSecurityConfigurerAdapter; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.access.intercept.FilterSecurityInterceptor; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; /** * @Description : * @Author: Liruilong * @Date: 2019/12/18 19:11 */ @Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired HrService hrService; @Autowired CustomFilterInvocationSecurityMetadataSource customFilterInvocationSecurityMetadataSource; @Autowired CustomUrlDecisionManager customUrlDecisionManager; @Autowired VerifyCodeFilter verifyCodeFilter ; @Autowired MyAuthenticationFailureHandler myAuthenticationFailureHandler; @Override protected void configure(HttpSecurity http) throws Exception { http.addFilterBefore(verifyCodeFilter, UsernamePasswordAuthenticationFilter.class) .authorizeRequests() //.anyRequest().authenticated() //所有请求的都会经过这进行鉴权处理。返回当前请求需要的角色。 .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() { @Override public <O extends FilterSecurityInterceptor> O postProcess(O object) { object.setSecurityMetadataSource(customFilterInvocationSecurityMetadataSource); object.setAccessDecisionManager(customUrlDecisionManager); return object; } }) .and().formLogin().usernameParameter("username").passwordParameter("password") //设置登录请求的url路径 .loginProcessingUrl("/doLogin") /*需要身份验证时,将浏览器重定向到/ login 我们负责在请求/ login时呈现登录页面 当身份验证尝试失败时,将浏览器重定向到/ login?error(因为我们没有另外指定) 当请求/ login?error时,我们负责呈现失败页面 成功注销后,将浏览器重定向到/ login?logout(因为我们没有另外指定) 我们负责在请求/ login?logout时呈现注销确认页面*/ .loginPage("/login") //登录成功回调 .successHandler(new AuthenticationSuccessHandler() { @Override public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException { httpServletResponse.setContentType("application/json;charset=utf-8"); PrintWriter out = httpServletResponse.getWriter(); Hr hr = (Hr) authentication.getPrincipal(); //密码不回传 hr.setPassword(null); RespBean ok = RespBean.ok("登录成功!", hr); //将hr转化为Sting String s = new ObjectMapper().writeValueAsString(ok); out.write(s); out.flush(); out.close(); } }) //登失败回调 .failureHandler(myAuthenticationFailureHandler) //相关的接口直接返回 .permitAll().and().logout() //注销登录 .logoutSuccessHandler(new LogoutSuccessHandler() { @Override public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException { httpServletResponse.setContentType("application/json;charset=utf-8"); PrintWriter out = httpServletResponse.getWriter(); out.write(new ObjectMapper().writeValueAsString(RespBean.ok("注销成功!"))); out.flush(); out.close(); } }) .permitAll().and().csrf().disable().exceptionHandling() //没有认证时,在这里处理结果,不要重定向 .authenticationEntryPoint( //myAuthenticationEntryPoint; new AuthenticationEntryPoint() { @Override public void commence(HttpServletRequest req, HttpServletResponse resp, AuthenticationException authException) throws IOException, ServletException { resp.setContentType("application/json;charset=utf-8"); resp.setStatus(401); PrintWriter out = resp.getWriter(); RespBean respBean = RespBean.error("访问失败!"); if (authException instanceof InsufficientAuthenticationException) { respBean.setMsg("请求失败,请联系管理员!"); } out.write(new ObjectMapper().writeValueAsString(respBean)); out.flush(); out.close(); } }); } @Bean PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(hrService); } /** * @Author Liruilong * @Description 放行的请求路径 * @Date 19:25 2020/2/7 * @Param [web] * @return void **/ @Override public void configure(WebSecurity web) throws Exception { web.ignoring().antMatchers("/auth/code","/login","/css/**","/js/**", "/index.html", "/img/**", "/fonts/**","/favicon.ico"); } }