SpringSecurity学习笔记

SpringSecurity学习笔记

1、SringSecurity概念总结

  • oAuth2是一种协议,他的主要作用是未了提供认证和授权的标准
  • oAuth2是标准,是协议就需要实现者,SpringSecurity、shiro都可以实现
  • 客户端授权模式有四种,简单模式、授权码模式、密码模式、客户端模式
  • 访问令牌:Access Token;Refresh Token:刷新令牌
  • jwt是oAuth2的一个扩展,一种管理token的方式。

2、web应用安全配置适配器

在这里插入图片描述

  • 安全就是两个事:认证、授权。formLogin表示采用表单登录的方式,指定身份认证的方式,

    UsernamePasswordAuthenticationFilter用来处理 formLogin表单登录方式;BasicAuthenticationFilter用来处理basic登录方式。

  • authorizeRequests表示需要对请求进行授权,授权配置有anyrequest任何请求都需要authenticated身份认证。

3、SpringSecurity原理

在这里插入图片描述

  • 过滤器作用:用来认证用户的身份,每一个过滤器负责处理一种认证方式。

  • 过滤器是可以通过配置来决定某一个过滤器是否生效,比如不配置httpBasic,BasicAuthenticationFilter过滤器就不会生效,只有绿色的过滤器是可配置,其余的不能。

  • 过滤器链上是可以配置多个过滤器的,看应用程序需要而定。

  • 当请求过来的时候UsernamePasswordAuthenticationFilter会判断请求是不是一个登录请求,是否包含用户名密码,如果包含就会用户名和密码登录,如果没带就会放过去给下一个过滤器,假如下一个过滤器是BasicAuthenticationFilter,就会检查请求头是否包含Basic开头的Authentication信息,若果有的话会进行Base64解码拿到用户名密码尝试登录,过滤器链上会有好多过滤器,都会按照这个原则一个一个校验,任何一个过滤器登录成功,会在请求上做标记当前用户已经登录成功。

  • 请求经过绿色的过滤器之后,最终会到FilterSecurityInterceptor,他是过滤器链的最后一环,他决定请求是否能访问最后的rest服务,他依据什么判断呢?依据授权配置,我们配置的是anyrequest任何请求都需要authenticated身份认证,FilterSecurityInterceptor就会判断是否满足我们的配置,满足后方可请求到rest服务。
    在这里插入图片描述

  • 请求没有认证通过的时候,就会抛出异常,ExceptionTranslationFilter会捕获抛出的异常,他会根据认证方式,引导用户去登录,比如说前边配置的是UsernamePasswordAuthenticationFilter就会把用户引导到登录页面上去,如果是BasicAuthenticationFilter就会弹窗,让用户输入用户名密码

4、自定义用户认证逻辑

4.1、处理用户信息获取

在这里插入图片描述

  • SpringSecurity获取用户信息的逻辑封装在UserDetailsService接口里边,需要实现这个接口的方法loadUserByUserName,通过用户输入的用户名获取用户信息

  • 用户信息被封装在UserDetails的接口实现类里边,返回用户信息后SpringSecurity会拿着获取到的用户信息做一些校验,若果认证校验通过会把用户信息放到session里边,不通过就会报错

  • Security里的User类实现了UserDetails接口,返回值可以自定义只要实现UserDetails接口就行。

4.2、用户校验逻辑实现
  • 上边的四个boolean参数,代表UserDetails接口中四个可以实现的方法

    boolean isAccountNonExpired() :返回true表示账号没有过期

    boolean isAccountNonLocked() :返回true表示账号没有被锁定

    boolean isCredentialsNonExpired() :返回true表示密码没有过期

    boolean isEnabled() :返回true表示用户没有被删除

4.3、SpringSecurity用来处理加密、解密

在这里插入图片描述

在这里插入图片描述

  • SpringSecurity提供一个加密解密的接口类PasswordEncoder,BCryptPasswordEncoder实现了这个接口,也可以自己实现这个接口。
  • encode是加密方法,mathes是校验密码是否一致。
  • BCryptPasswordEncoder同一个密码每次加密的结果都不一样,因为每次加密都会生成一个随机盐
  • BCryptPasswordEncoder方法采用SHA-256 +随机盐+密钥,对密码进行加密,SHA系列是Hash算法,不是加密算法。

5、个性化认证流程

5、1自定义登录界面

在这里插入图片描述
在这里插入图片描述

  • loginPage() 指定自定义的登录页面

  • UsernamePasswordAuthenticationFilter过滤器处理的是一个login的登录请求,loginProcessingUrl指定这个请求用UsernamePasswordAuthenticationFilter来处理

  • antMatchers(),permitAll()指定该页面不需要校验什么就可以访问

  • 请求一个rest服务,UsernamePasswordAuthenticationFilter发现没有登录,校验不通过,跳转到登录页面上去,登录成功后即可访问rest服务。

  • CSRF是SpringSecurity提供的跨站伪造防护,暂时先关闭了。

5.2、SpringSecurity表单验证处理不同类型的请求

在这里插入图片描述
@RequestMapping(SecurityConstants.DEFAULT_UNAUTHENTICATION_URL)
@ResponseStatus(code = HttpStatus.UNAUTHORIZED)
public SimpleResponse requireAuthentication(HttpServletRequest request, HttpServletResponse response)throws IOException {

	SavedRequest savedRequest = requestCache.getRequest(request, response);
	if (savedRequest != null) {
		String targetUrl = savedRequest.getRedirectUrl();
		//自定义controller,请求服务校验失败后,跳转倒我们自定义的controller上,
        //如果发现请求的是一个html页面,就条抓到登陆页,如果发现请求不是一个html页面就
        //返回json传异常信息。
		if (StringUtils.endsWithIgnoreCase(targetUrl, ".html")) {
			redirectStrategy.sendRedirect(request, response,                     					securityProperties.getBrowser().getLoginPage());
		}
	}
	return new SimpleResponse("访问的服务需要身份认证,请引导用户到登录页");
}

在这里插入图片描述

  • 自定义Controller,并修改配置登录请求的时候跳转到我们自定义的Controller里边,在自定义的controller里边判断请求是不是一个html页面。

  • 请求一个rest服务,UsernamePasswordAuthenticationFilter校验不通过,跳转到我们自定义的controller上,因为请求不是html页面,返回json异常信息{“content”:“访问的服务需要身份认证,引导用户登录”}。(场景:访问一个服务发现用户超时,根绝返回的错误跳转到登录页)

  • 请求一个html页面,UsernamePasswordAuthenticationFilter校验不通过,跳转到我们自定义的controller上,判断请求的是一个html页面,就直接跳转到登录页

  • 5.3、自定义登录成功处理
  • SpringSecurity默认处理方式:请求一个rest服务,SpringSecurity过滤器校验失败,就会跳转到登录页上,登录成功后悔重新重定向到引发登录跳转的请求。

  • 自定义登录成功处理接口:只需要实现AuthenticationSuccessHandler接口,SavedRequestAwareAuthenticationSuccessHandler就是SpringSecurity的***默认处理方式***,

@Component("imoocAuthenticationSuccessHandler")
public class ImoocAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {

	private Logger logger = LoggerFactory.getLogger(getClass());
	@Autowired
	private ObjectMapper objectMapper;
	@Autowired
	private SecurityProperties securityProperties;
	@Override
	public void onAuthenticationSuccess(HttpServletRequest request, 		     				HttpServletResponse response,Authentication authentication) 
            throws IOException, ServletException {
        //可以根据我们自己的配置,判断是返回json还是继续使用默认处理方式。
		if (LoginResponseType.JSON.equals(
            securityProperties.getBrowser().getLoginType())) {
			response.setContentType("application/json;charset=UTF-8");
			response.getWriter().write(
                objectMapper.writeValueAsString(authentication));
		} else {
            //super调用父类SavedRequestAwareAuthenticationSuccessHandler默认的处理方式
            //默认处理方式:登录成功后悔重新重定向到引发登录跳转的请求。
			super.onAuthenticationSuccess(request, response, authentication);
		}
	}
}
@Component("imoocAuthenctiationFailureHandler")
public class ImoocAuthenctiationFailureHandler extends SimpleUrlAuthenticationFailureHandler {

	private Logger logger = LoggerFactory.getLogger(getClass());
	@Autowired
	private ObjectMapper objectMapper;
	@Autowired
	private SecurityProperties securityProperties;
	@Override
	public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
			AuthenticationException exception) throws IOException, ServletException {		
		if (LoginResponseType.JSON.equals(
            securityProperties.getBrowser().getLoginType())) {
			response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
			response.setContentType("application/json;charset=UTF-8");
			response.getWriter()
                .write(objectMapper
                       .writeValueAsString(
                           new SimpleResponse(exception.getMessage())));
		}else{
			super.onAuthenticationFailure(request, response, exception);
		}
	}
}
  • 过滤器链上配置successHandler及failuerHandler
  • 在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值