文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

spring security中的默认登录页源码分析

2023-06-25 13:37

关注

这篇文章主要讲解了“spring security中的默认登录页源码分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“spring security中的默认登录页源码分析”吧!

springboot项目依赖

<dependency>   <groupId>org.springframework.boot</groupId>   <artifactId>spring-boot-starter-web</artifactId></dependency><dependency>   <groupId>org.springframework.boot</groupId>   <artifactId>spring-boot-starter-security</artifactId></dependency>

在项目中随意编写一个接口,然后进行访问

@GetMapping("/")public String hello() {   return "hello, spring security";}

在tomcat默认端口8080,localhost:8080 下访问该接口,spring security会帮我们将路径重定向到默认的登录页

spring security中的默认登录页源码分析

那么这个默认页是怎么来的呢?
原来Spring Security有一个默认的WebSecurityConfigurerAdapter,发现其中有一个init方法,于是在这个方法打了断点,在应用启动的时候进行跟踪。

跟踪getHttp()方法,this.disableDefaults变量默认为false,意味着将会执行applyDefaultConfiguration(this.http);方法。查看applyDefaultConfiguration方法

public void init(WebSecurity web) throws Exception {    // 首先配置security要拦截的哪些http请求   HttpSecurity http = getHttp();   web.addSecurityFilterChainBuilder(http).postBuildAction(() -> {      FilterSecurityInterceptor securityInterceptor = http.getSharedObject(FilterSecurityInterceptor.class);      web.securityInterceptor(securityInterceptor);   });}protected final HttpSecurity getHttp() throws Exception {if (this.http != null) {return this.http;}AuthenticationEventPublisher eventPublisher = getAuthenticationEventPublisher();this.localConfigureAuthenticationBldr.authenticationEventPublisher(eventPublisher);AuthenticationManager authenticationManager = authenticationManager();this.authenticationBuilder.parentAuthenticationManager(authenticationManager);Map<Class<?>, Object> sharedObjects = createSharedObjects();this.http = new HttpSecurity(this.objectPostProcessor, this.authenticationBuilder, sharedObjects);if (!this.disableDefaults) {            // 默认的配置将会走这个分支applyDefaultConfiguration(this.http);ClassLoader classLoader = this.context.getClassLoader();List<AbstractHttpConfigurer> defaultHttpConfigurers = SpringFactoriesLoader.loadFactories(AbstractHttpConfigurer.class, classLoader);for (AbstractHttpConfigurer configurer : defaultHttpConfigurers) {this.http.apply(configurer);}}configure(this.http);return this.http;}

查看applyDefaultConfiguration(this.http)方法,发现http对象new了一个DefaultLoginPageConfigurer对象属性,

private void applyDefaultConfiguration(HttpSecurity http) throws Exception {   http.csrf();   http.addFilter(new WebAsyncManagerIntegrationFilter());   http.exceptionHandling();   http.headers();   http.sessionManagement();   http.securityContext();   http.requestCache();   http.anonymous();   http.servletApi();   http.apply(new DefaultLoginPageConfigurer<>());   http.logout();}

查看DefaultLoginPageConfigurer类定义,发现它在初始化的同时,它也初始化了自己的2个私有成员变量,分别是DefaultLoginPageGeneratingFilter默认登录页面生成Filter,DefaultLogoutPageGeneratingFilter默认登录页面Filter, 名字起得很好,见名知意,我们马山知道这2个类的含义。

查看DefaultLoginPageGeneratingFilter的类成员变量,发现定义了一系列跟登录有关的成员变量,包括登录、登录等路径,默认的登录页面路径是"/login"

public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {   public static final String DEFAULT_LOGIN_PAGE_URL = "/login";   public static final String ERROR_PARAMETER_NAME = "error";   private String loginPageUrl;   private String logoutSuccessUrl;   private String failureUrl;   private boolean formLoginEnabled;    .....

再结合类名思考,发现是个Filter类,那么它们应该都会重新Filter的doFilter(ServletRequest request, ServletResponse response, FilterChain chain)方法,我们查看一下DefaultLoginPageConfigurer类的``doFilter方法,果然,在doFilter`方法中发现了生成默认登录页面的方法。

private void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)      throws IOException, ServletException {    // 判断当前的请求是否被认证通过   boolean loginError = isErrorPage(request);   boolean logoutSuccess = isLogoutSuccess(request);   if (isLoginUrlRequest(request) || loginError || logoutSuccess) {       // 当前请求认证失败的话,将会执行这个分支      String loginPageHtml = generateLoginPageHtml(request, loginError, logoutSuccess);      response.setContentType("text/html;charset=UTF-8");      response.setContentLength(loginPageHtml.getBytes(StandardCharsets.UTF_8).length);      response.getWriter().write(loginPageHtml);      return;   }   chain.doFilter(request, response);}private String generateLoginPageHtml(HttpServletRequest request, boolean loginError, boolean logoutSuccess) {   String errorMsg = "Invalid credentials";   if (loginError) {      HttpSession session = request.getSession(false);      if (session != null) {         AuthenticationException ex = (AuthenticationException) session               .getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);         errorMsg = (ex != null) ? ex.getMessage() : "Invalid credentials";      }   }   String contextPath = request.getContextPath();   StringBuilder sb = new StringBuilder();   sb.append("<!DOCTYPE html>\n");   sb.append("<html lang=\"en\">\n");   sb.append("  <head>\n");   sb.append("    <meta charset=\"utf-8\">\n");   sb.append("    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n");   sb.append("    <meta name=\"description\" content=\"\">\n");   sb.append("    <meta name=\"author\" content=\"\">\n");   sb.append("    <title>Please sign in</title>\n");   sb.append("    <link href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" "         + "rel=\"stylesheet\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n");   sb.append("    <link href=\"https://getbootstrap.com/docs/4.0/examples/signin/signin.css\" "         + "rel=\"stylesheet\" crossorigin=\"anonymous\"/>\n");   sb.append("  </head>\n");   sb.append("  <body>\n");   sb.append("     <div class=\"container\">\n");   if (this.formLoginEnabled) {      sb.append("      <form class=\"form-signin\" method=\"post\" action=\"" + contextPath            + this.authenticationUrl + "\">\n");      sb.append("        <h3 class=\"form-signin-heading\">Please sign in</h3>\n");      sb.append(createError(loginError, errorMsg) + createLogoutSuccess(logoutSuccess) + "        <p>\n");      sb.append("          <label for=\"username\" class=\"sr-only\">Username</label>\n");      sb.append("          <input type=\"text\" id=\"username\" name=\"" + this.usernameParameter            + "\" class=\"form-control\" placeholder=\"Username\" required autofocus>\n");      sb.append("        </p>\n");      sb.append("        <p>\n");      sb.append("          <label for=\"password\" class=\"sr-only\">Password</label>\n");      sb.append("          <input type=\"password\" id=\"password\" name=\"" + this.passwordParameter            + "\" class=\"form-control\" placeholder=\"Password\" required>\n");      sb.append("        </p>\n");      sb.append(createRememberMe(this.rememberMeParameter) + renderHiddenInputs(request));      sb.append("        <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n");      sb.append("      </form>\n");   }   if (this.openIdEnabled) {      sb.append("      <form name=\"oidf\" class=\"form-signin\" method=\"post\" action=\"" + contextPath            + this.openIDauthenticationUrl + "\">\n");      sb.append("        <h3 class=\"form-signin-heading\">Login with OpenID Identity</h3>\n");  ......   return sb.toString();}

我们发现generateLoginPageHtml(HttpServletRequest request, boolean loginError, boolean logoutSuccess)这个方法中使用了最原始的Servlet写html页面的方法,将登录页的html代码写到字符串中写出到前端展示。

感谢各位的阅读,以上就是“spring security中的默认登录页源码分析”的内容了,经过本文的学习后,相信大家对spring security中的默认登录页源码分析这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯