SpringSecurity 你值得学习!!!

JAVA安全框架简介

SpringSecurity功能介绍和原理分析

一、基本原理

基于servlet的Filter来实现的!!

在这里插入图片描述

绿色部分的各个过滤器(如 UsernamePasswordAuthenticationFilter),主要完成SpringSecurity的各种认证工作,如Form表单认证(登录页)和 http basic认证等
黄色的 FilterSecurityInterceptor 是整个过滤器链中的最后一环,最终由它决定当前请求能否到达最后请求的资源
蓝色的ExceptionTranslationFilter过滤器,用于捕获FilterSecurityInterceptor抛出的各种异常,进行对应的处理

默认的过滤器链:

在这里插入图片描述

二、认证流程详解

在这里插入图片描述

认证成功后认证结果在多个请求之间实现共享

在这里插入图片描述

SecurityContextPersistenceFilter实现认证结果共享

在这里插入图片描述

UsernamePasswordAuthenticationFilter: 用户名和密码认证的过滤器

调用父类的AbstractAuthenticationProcessingFilter的doFilter进行认证:

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
      throws IOException, ServletException {
   

    。。。。。
  
      authResult = attemptAuthentication(request, response);//认证
     。。。。
   }
   catch (InternalAuthenticationServiceException failed) {
   
      logger.error(
            "An internal error occurred while trying to authenticate the user.",
            failed);
      unsuccessfulAuthentication(request, response, failed);

      return;
   }
   catch (AuthenticationException failed) {
   
      // Authentication failed
      unsuccessfulAuthentication(request, response, failed);

      return;
   }

   successfulAuthentication(request, response, chain, authResult);
}

UsernamePasswordAuthenticationFilter:

public Authentication attemptAuthentication(HttpServletRequest request,
      HttpServletResponse response) throws AuthenticationException {
   
  ....
   UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
         username, password);
    ....
   return this.getAuthenticationManager().authenticate(authRequest);//交由认证管理器进行认证操作
}

认证管理器:

ProviderManager(默认的认证管理器)

public Authentication authenticate(Authentication authentication)
      throws AuthenticationException {
   
    。。。。
        
   //遍历所有的认证提供者,找一个合适的认证提供者来处理请求
   for (AuthenticationProvider provider : getProviders()) {
   
      if (!provider.supports(toTest)) {
   
         continue;
      }

      try {
   
         result = provider.authenticate(authentication);

         if (result != null) {
   
            copyDetails(authentication, result);
            break;
         }
      }

   }
    。。。。
}

DaoAuthenticationProvider:

调用父类AbstractUserDetailsAuthenticationProvider的authenticate进行认证

public Authentication authenticate(Authentication authentication)
      throws AuthenticationException {
   
   Assert.isInstanceOf(UsernamePasswordAuthenticationToken.class, authentication,
         messages.getMessage(
               "AbstractUserDetailsAuthenticationProvider.onlySupports",
               "Only UsernamePasswordAuthenticationToken is supported"));

   // Determine username
   String username = (authentication.getPrincipal() == null) ? "NONE_PROVIDED"
         : authentication.getName();

   boolean cacheWasUsed = true;
   UserDetails user = this.userCache.getUserFromCache(username);

   if (user == null) {
   
      try {
   
          //获取真实的用户信息
         user = retrieveUser(username,
               (UsernamePasswordAuthenticationToken) authentication);
      }
    
   }

   try {
   
      ......
      //用户认证
      additionalAuthenticationChecks(user,
            (UsernamePasswordAuthenticationToken) authentication);
   }
   
   return createSuccessAuthentication(principalToReturn, authentication, user);
}

DaoAuthenticationProvider:

retrieveUser:

protected final UserDetails retrieveUser(String username,
      UsernamePasswordAuthenticationToken authentication)
      throws AuthenticationException {
   
    
   try {
   
       
      UserDetails loadedUser = this.getUserDetailsService().loadUserByUsername(username);
    
      return loadedUser;
   }
  
}

additionalAuthenticationChecks:

protected void additionalAuthenticationChecks(UserDetails userDetails,
      UsernamePasswordAuthenticationToken authentication)
      throws AuthenticationException {
   
    
   String presentedPassword = authentication.getCredentials().toString();
    //密码比对
   if (!passwordEncoder.matches(presentedPassword, userDetails.getPassword())) {
   
      throw new BadCredentialsException(messages.getMessage(
            "AbstractUserDetailsAuthenticationProvider.badCredentials",
            "Bad credentials"));
   }
}

三、个性化用户认证流程

需求:修改登录时的默认表单请求为ajax异步请求!!!

login(){
   
  axios.post('/login.do','username='+this.username+'&password='+this.password+"&imageCode="+this.imageCode+"&imageCode="+this.imageCode
                        +'&rememberMe='+this.rememberMe).then((res)=>{
   
                        if(res.data.flag){
   
                            window.location.href="/pages/main.html";
                        }else{
   
                            this.msg=res.data.message;
                        }
                    });
}

1、修改登录成功后返回json数据

接口及常用实现类

AuthenticationSuccessHandler
--SavedRequestAwareAuthenticationSuccessHandler  默认
--ForwardAuthenticationSuccessHandler
--SimpleUrlAuthenticationSuccessHandler

自定义认证成功处理器

public class AuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
   
    private String type;

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                                        Authentication authentication) throws IOException, ServletException {
   
        logger.info("登录成功");
        if ("json".equalsIgnoreCase(this.type) || "json".equalsIgnoreCase(request.getParameter("type"))) {
   
            //返回json格式数据
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write("{\"flag\":true,\"message\":\"登录成功\"}");
        } else {
   //默认的页面跳转
            super.onAuthenticationSuccess(request, response, authentication);
        }

    }
    public String getType() {
   
        return type;
    }
    public void setType(String type) {
   
        this.type = type;
    }

}

配置

<security:form-login   
		login-page="/login.jsp" 
		default-target-url="/index.html" 
		authentication-failure-url="/login.jsp"
		authentication-success-handler-ref="authenticationSuccessHandler"/>

<bean id="authenticationSuccessHandler" class="com.itheima.AuthenticationSuccessHandler">
    <property name="type" value="json"></property>
</bean>

2、修改处理登录失败后返回json数据

接口及常用实现类

AuthenticationFailureHandler
--SimpleUrlAuthenticationFailureHandler    默认
--DelegatingAuthenticationFailureHandler
--ForwardAuthenticationFailureHandler

自定义认证失败处理器

public 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值