Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >SpringSecurity默认页面生成分析

SpringSecurity默认页面生成分析

作者头像
周杰伦本人
发布于 2022-10-25 09:16:56
发布于 2022-10-25 09:16:56
32800
代码可运行
举报
文章被收录于专栏:同步文章同步文章
运行总次数:0
代码可运行

默认页面生成

springSecurity过滤器

  • DefaultLoginPageGeneratingFilter 生成默认的登录页面
  • DefaultLogoutPageGeneratingFilter 生成默认的注销页面

DefaultLoginPageGeneratingFilter

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
    HttpServletRequest request = (HttpServletRequest)req;
    HttpServletResponse response = (HttpServletResponse)res;
    boolean loginError = this.isErrorPage(request);
    boolean logoutSuccess = this.isLogoutSuccess(request);
    if (!this.isLoginUrlRequest(request) && !loginError && !logoutSuccess) {
        chain.doFilter(request, response);
    } else {
        String loginPageHtml = this.generateLoginPageHtml(request, loginError, logoutSuccess);
        response.setContentType("text/html;charset=UTF-8");
        response.setContentLength(loginPageHtml.getBytes(StandardCharsets.UTF_8).length);
        response.getWriter().write(loginPageHtml);
    }
}

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("SPRING_SECURITY_LAST_EXCEPTION");
            errorMsg = ex != null ? ex.getMessage() : "Invalid credentials";
        }
    }

    StringBuilder sb = new StringBuilder();
    sb.append("<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n    <meta name=\"description\" content=\"\">\n    <meta name=\"author\" content=\"\">\n    <title>Please sign in</title>\n    <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    <link href=\"https://getbootstrap.com/docs/4.0/examples/signin/signin.css\" rel=\"stylesheet\" crossorigin=\"anonymous\"/>\n  </head>\n  <body>\n     <div class=\"container\">\n");
    String contextPath = request.getContextPath();
    if (this.formLoginEnabled) {
        sb.append("      <form class=\"form-signin\" method=\"post\" action=\"" + contextPath + this.authenticationUrl + "\">\n        <h2 class=\"form-signin-heading\">Please sign in</h2>\n" + createError(loginError, errorMsg) + createLogoutSuccess(logoutSuccess) + "        <p>\n          <label for=\"username\" class=\"sr-only\">Username</label>\n          <input type=\"text\" id=\"username\" name=\"" + this.usernameParameter + "\" class=\"form-control\" placeholder=\"Username\" required autofocus>\n        </p>\n        <p>\n          <label for=\"password\" class=\"sr-only\">Password</label>\n          <input type=\"password\" id=\"password\" name=\"" + this.passwordParameter + "\" class=\"form-control\" placeholder=\"Password\" required>\n        </p>\n" + this.createRememberMe(this.rememberMeParameter) + this.renderHiddenInputs(request) + "        <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n      </form>\n");
    }

    if (this.openIdEnabled) {
        sb.append("      <form name=\"oidf\" class=\"form-signin\" method=\"post\" action=\"" + contextPath + this.openIDauthenticationUrl + "\">\n        <h2 class=\"form-signin-heading\">Login with OpenID Identity</h2>\n" + createError(loginError, errorMsg) + createLogoutSuccess(logoutSuccess) + "        <p>\n          <label for=\"username\" class=\"sr-only\">Identity</label>\n          <input type=\"text\" id=\"username\" name=\"" + this.openIDusernameParameter + "\" class=\"form-control\" placeholder=\"Username\" required autofocus>\n        </p>\n" + this.createRememberMe(this.openIDrememberMeParameter) + this.renderHiddenInputs(request) + "        <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n      </form>\n");
    }

    Iterator var7;
    Entry relyingPartyUrlToName;
    String url;
    String partyName;
    if (this.oauth2LoginEnabled) {
        sb.append("<h2 class=\"form-signin-heading\">Login with OAuth 2.0</h2>");
        sb.append(createError(loginError, errorMsg));
        sb.append(createLogoutSuccess(logoutSuccess));
        sb.append("<table class=\"table table-striped\">\n");
        var7 = this.oauth2AuthenticationUrlToClientName.entrySet().iterator();

        while(var7.hasNext()) {
            relyingPartyUrlToName = (Entry)var7.next();
            sb.append(" <tr><td>");
            url = (String)relyingPartyUrlToName.getKey();
            sb.append("<a href=\"").append(contextPath).append(url).append("\">");
            partyName = HtmlUtils.htmlEscape((String)relyingPartyUrlToName.getValue());
            sb.append(partyName);
            sb.append("</a>");
            sb.append("</td></tr>\n");
        }

        sb.append("</table>\n");
    }

    if (this.saml2LoginEnabled) {
        sb.append("<h2 class=\"form-signin-heading\">Login with SAML 2.0</h2>");
        sb.append(createError(loginError, errorMsg));
        sb.append(createLogoutSuccess(logoutSuccess));
        sb.append("<table class=\"table table-striped\">\n");
        var7 = this.saml2AuthenticationUrlToProviderName.entrySet().iterator();

        while(var7.hasNext()) {
            relyingPartyUrlToName = (Entry)var7.next();
            sb.append(" <tr><td>");
            url = (String)relyingPartyUrlToName.getKey();
            sb.append("<a href=\"").append(contextPath).append(url).append("\">");
            partyName = HtmlUtils.htmlEscape((String)relyingPartyUrlToName.getValue());
            sb.append(partyName);
            sb.append("</a>");
            sb.append("</td></tr>\n");
        }

        sb.append("</table>\n");
    }

    sb.append("</div>\n");
    sb.append("</body></html>");
    return sb.toString();
}

(1) 在doFilter方法中 首先判断当前请求是否为登录出错请求,注销成功请求或者登录请求。如果这三个请求中的任意一个,就会在DefaultLoginPageGeneratingFilter中生成登录页面并返回,否则请求继续往下走,执行下一个过滤器。

  1. 如果当前请求为登录出错请求,注销成功请求或者登录请求,使用generateLoginPageHtml生成登录页面,如果有异常信息一同返回给前端
  2. 登录页面生成后通过HttpServletResponse将登录页面写回到前端,然后调用return方法跳出过滤器链。

DefaultLogoutPageGeneratingFilter

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
    if (this.matcher.matches(request)) {
        this.renderLogout(request, response);
    } else {
        filterChain.doFilter(request, response);
    }

}

private void renderLogout(HttpServletRequest request, HttpServletResponse response) throws IOException {
    String page = "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n    <meta name=\"description\" content=\"\">\n    <meta name=\"author\" content=\"\">\n    <title>Confirm Log Out?</title>\n    <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    <link href=\"https://getbootstrap.com/docs/4.0/examples/signin/signin.css\" rel=\"stylesheet\" crossorigin=\"anonymous\"/>\n  </head>\n  <body>\n     <div class=\"container\">\n      <form class=\"form-signin\" method=\"post\" action=\"" + request.getContextPath() + "/logout\">\n        <h2 class=\"form-signin-heading\">Are you sure you want to log out?</h2>\n" + this.renderHiddenInputs(request) + "        <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Log Out</button>\n      </form>\n    </div>\n  </body>\n</html>";
    response.setContentType("text/html;charset=UTF-8");
    response.getWriter().write(page);
}

请求到来之后,先判断是否注销请求/logout,如果是/logout请求,则渲染一个注销请求的页面,否则走下一个过滤器。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-06-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【第三篇】开始和SpringSecurity的简单交往-处理请求的本质
分析SpringSecurity的核心原理,那么我们从哪开始分析?以及我们要分析哪些内容?
用户4919348
2022/05/10
3100
【第三篇】开始和SpringSecurity的简单交往-处理请求的本质
SpringSecurity:高级应用
分析SpringSecurity的核心原理,那么我们从哪开始分析?以及我们要分析哪些内容?
Java鱼头
2022/11/30
8121
权限框架 | 学会Spring Security权限框架,就是这么简单
Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架(简单说是对访问权限进行控制 )。
码神联盟
2019/07/31
4.5K0
权限框架 | 学会Spring Security权限框架,就是这么简单
Django——登录功能
现在将此页面的的body拿下来,然后运行项目,你会发现,这个效果和bootstrap上的还是不一样,这是因为缺少了一些css,我们把CSS也拿下来。
zy010101
2021/01/13
1.6K0
Django——登录功能
XXE靶机实践
Haboob团队根据https://www.exploit-db.com/docs/45374发表的论文"XML外部实体注入-解释和利用"制作了这个虚拟机以利用私有网络中的漏洞,我们希望你喜欢这个挑战!
Al1ex
2023/12/22
2790
聊聊如何对eureka管理界面进行定制化改造
在nacos还未面世之前,eureka基本上就是springcloud全家桶体系注册中心的首选,随着nacos的横空出世,越来越多基于springcloud的微服务项目采用nacos作为注册中心,但这是不是意味着eureka就没用武之地,其实并不是的,从springcloud截止目前最新版本2020.0.2来看,该版本废弃了netflix诸如hytrix、ribbon、zuul等组件,而eureka仍然坚挺着,这就说明eureka作为注册中心,在springcloud体系中仍然发挥着重要的作用。今天就来聊聊如何对eureka管理界面进行定制化改造
lyb-geek
2021/04/12
1.3K0
聊聊如何对eureka管理界面进行定制化改造
聊聊如何对eureka管理界面进行定制化改造
在nacos还未面世之前,eureka基本上就是springcloud全家桶体系注册中心的首选,随着nacos的横空出世,越来越多基于springcloud的微服务项目采用nacos作为注册中心,但这是不是意味着eureka就没用武之地,其实并不是的,从springcloud截止目前最新版本2020.0.2来看,该版本废弃了netflix诸如hytrix、ribbon、zuul等组件,而eureka仍然坚挺着,这就说明eureka作为注册中心,在springcloud体系中仍然发挥着重要的作用。今天就来聊聊如何对eureka管理界面进行定制化改造
lyb-geek
2022/01/07
6240
聊聊如何对eureka管理界面进行定制化改造
基于 Go 语言开发在线论坛(四):通过 Cookie + Session 实现用户认证
在此之前,我们现在 handlers 目录下创建一个 helper.go 文件,用于定义一些全局辅助函数(主要用在处理器中):
学院君
2020/04/02
5750
基于 Go 语言开发在线论坛(四):通过 Cookie + Session 实现用户认证
ssh登录实现
工程目录 配置文件详解 Spring的applicationContext.xml文件 <span ><?xml version="1.0" encoding="UTF-8"?> <beans
用户1141560
2017/12/26
2.6K0
ssh登录实现
CRM客户关系管理系统(二) 第三章、前端页面设计
第三章、前端页面设计  3.1.前端页面布局 Bootstrap模板下载  (1)静态文件 新建statics目录(存放css/fonts/imgs/js/plugins) settings配置 STATIC_URL = '/static/' STATICFILES_DIRS = ( os.path.join(BASE_DIR, 'statics'), ) (2)模板文件  templates下新建crm目录,把Dashboard Template for Bootstrap.html放到里面,命
zhang_derek
2018/05/30
3.3K0
Django 用户登陆访问限制 @login_required
在网站开发过程中,经常会遇到这样的需求:用户登陆系统才可以访问某些页面,如果用户没有登陆而直接访问就会跳转到登陆界面。
菲宇
2019/06/13
1.5K0
BBS论坛(二)
2.1.cms后台登录界面完成 (1)templates/cms/cms_login.html <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <
zhang_derek
2019/02/13
4.2K0
BBS论坛(二)
Python全栈(八)Flask项目实战之1.项目搭建
Falsk项目实战是做一个简单的论坛平台,实现基本功能。 Github和Gitee代码同步更新: https://github.com/PythonFullStack/Flask_BBS; https://gitee.com/Python_Full_Stack/Flask_BBS。
cutercorley
2020/07/23
2K0
Python全栈(八)Flask项目实战之1.项目搭建
Nodejs学习笔记(七)--- Node.js + Express 构建网站简单示例
前言   上一篇学习了一些构建网站会用到的一些知识点 https://cloud.tencent.com/developer/article/1020636   这一篇主要结合前面讲到的知识,去构建一个较为完整的网站应用程序,对前面学到的一些知道做一个串联加深并灵活运用!   功能主要用MySQL数据库,包括登录、注册、主页三部分;下面就一步步开始吧! 新建项目、建立数据库以及其它准备工作 1.新建express + ejs 项目:sampleEjs cd 工作目录 express -e sampleEj
Porschev
2018/01/16
3.8K0
Nodejs学习笔记(七)--- Node.js + Express 构建网站简单示例
ChatGPT与基于GUI的自动化测试
当使用Edge浏览器结合Selenium框架生成百度查询测试代码时,你可以使用以下Python代码示例:
顾翔
2024/09/10
1790
ChatGPT与基于GUI的自动化测试
SpringSecurity6 | 核心过滤器
大家好,我是Leo哥🫣🫣🫣,上一节我们通过源码剖析以及图文分析,了解了关于委派筛选器代理和过滤器链代理的原理和作用。这节课我们接着学习SpringSecurity的过滤器,了解SpringSecurity中都有哪些核心过滤器。好了,话不多说让我们开始吧😎😎😎。
程序员Leo
2023/11/17
1K0
SpringSecurity6 | 核心过滤器
三、模板变量及模板过滤器
其中,第一种方式的优先级高,模板引擎会优先搜索第一种方式中的模板文件,如果不存在才会搜索第二种方式中的模板文件。引擎只要找到符合要求的模板就会返回。
py3study
2020/01/16
9110
SpringBoot项目复盘
如果后端数据判断显示为null或者密码错误。通过上述的语法就可以实现将数据回显出来,而不是一开始就显示数据
用户11097514
2024/05/30
1360
SpringBoot项目复盘
Nodejs学习笔记(八)--- Node.js + Express 实现上传文件功能(felixge/node-formidable)
前言   前面讲了一个构建网站的示例,这次在此基础上再说说web的常规功能----文件上传,示例以一个上传图片的功能为例子   上传功能命名用formidable实现,示例很简单!   PS:最近比较忙,距上一次更新已经比较久了^_^! formidable简介   nodejs原生实现上传还是比较麻烦,有兴趣的自已去参考一下网上有网友写的代码   这里选择了formidable,也是github上同类功能模块人气比较高的 https://github.com/felixge/node-formidabl
Porschev
2018/01/16
1.4K0
Nodejs学习笔记(八)--- Node.js + Express 实现上传文件功能(felixge/node-formidable)
Spring Security内置过滤器详解
根据前面的示例,我们已经知道启动时会加载18个过滤器,并且已经知道了请求会匹配到DefaultSecurityFilterChain并依次通过这18个过滤器。
阿提说说
2022/12/02
1.1K0
推荐阅读
相关推荐
【第三篇】开始和SpringSecurity的简单交往-处理请求的本质
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验