使用Spring Security作为权限管理模块的小伙伴们一定醉心于其极少的配置即可满足权限管理需求,以及比springMVC更简洁的filter配置。

在刚开始技术验证的demo阶段相信很多人试过在什么都不配置的时候,只写个接口然后访问是会自动跳转到默认的登录页面"/login"。

按常理,一般人会好奇,这个登录页面在哪儿?应该是个模板引擎提供的模板,并且应该有个ModeAndView绑定的页面。

但实际上并不是。这个默认登录页面其实极其暴力简单。是一个默认filter里面直接写入response的。

在需要自定义实现的 WebSecurityConfigurerAdapter 中有这么一个方法。

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。它会添加两个默认filter

 public void configure(H http) {AuthenticationEntryPoint authenticationEntryPoint = null;ExceptionHandlingConfigurer<?> exceptionConf = http.getConfigurer(ExceptionHandlingConfigurer.class);if (exceptionConf != null) {authenticationEntryPoint = exceptionConf.getAuthenticationEntryPoint();}if (this.loginPageGeneratingFilter.isEnabled() && authenticationEntryPoint == null) {this.loginPageGeneratingFilter = postProcess(this.loginPageGeneratingFilter);http.addFilter(this.loginPageGeneratingFilter);http.addFilter(this.logoutPageGeneratingFilter);}}

其中loginPageGeneratingFilter中会生成登录页面

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("        <h2 class=\"form-signin-heading\">Please sign in</h2>\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("        <h2 class=\"form-signin-heading\">Login with OpenID Identity</h2>\n");sb.append(createError(loginError, errorMsg) + createLogoutSuccess(logoutSuccess) + "        <p>\n");sb.append("          <label for=\"username\" class=\"sr-only\">Identity</label>\n");sb.append("          <input type=\"text\" id=\"username\" name=\"" + this.openIDusernameParameter+ "\" class=\"form-control\" placeholder=\"Username\" required autofocus>\n");sb.append("        </p>\n");sb.append(createRememberMe(this.openIDrememberMeParameter) + 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.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");for (Map.Entry<String, String> clientAuthenticationUrlToClientName : this.oauth2AuthenticationUrlToClientName.entrySet()) {sb.append(" <tr><td>");String url = clientAuthenticationUrlToClientName.getKey();sb.append("<a href=\"").append(contextPath).append(url).append("\">");String clientName = HtmlUtils.htmlEscape(clientAuthenticationUrlToClientName.getValue());sb.append(clientName);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");for (Map.Entry<String, String> relyingPartyUrlToName : this.saml2AuthenticationUrlToProviderName.entrySet()) {sb.append(" <tr><td>");String url = relyingPartyUrlToName.getKey();sb.append("<a href=\"").append(contextPath).append(url).append("\">");String partyName = HtmlUtils.htmlEscape(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();}

没错,就是这么简单粗暴。连模板文件都没用,直接StringBuilder直接拼接的。是不是感觉spring的工程师也有一点都不优雅的时候。

其实这种写法有不好的一面也有好的一面。

坏的一面是:不够统一优雅。

好的一面是:为了尽量保证模块独立性。假设你不需要模板引擎,没必要因为默认登录页面还增加一大堆模板引擎的引入。减少各种原因引起使用方包冲突带来的额外工作。

本文算是给自己和其他还在试图找spring Security默认登录页面的小伙伴一个路牌,上面写着“别找了,没有页面模板的,都是我手动拼接的”

love & peace

Spring Security默认登录页面相关推荐

  1. spring security默认登录页面登录用户,和自定义数据源

    一.默认登录页面 请求 /hello 接口,在引入 spring security 之后会先经过一些列过滤器 在请求到达 FilterSecurityInterceptor时,发现请求并未认证.请求拦 ...

  2. Spring Security:自定义登录页面

    本文来说下Spring Security中如何自定义登录页面 文章目录 准备工作 自定义登录界面 本文小结 准备工作 添加模板引擎 这里使用了thymeleaf模板引擎,在pom.xml进行添加: & ...

  3. 关闭Spring security的登录验证

    目的关闭Spring security 默认登录页 Springboot 2.x关闭需要在启动类上排除SecurityAutoConfiguration和ManagementWebSecurityAu ...

  4. Spring Security默认的用户登录表单 页面源代码

    Spring Security默认的用户登录表单 页面源代码 <html><head><title>Login Page</title></hea ...

  5. spring security实现登录验证以及根据用户身份跳转不同页面

    想关依赖,采用session加redis存储用户信息 <dependency><groupId>org.springframework.security</groupId ...

  6. Spring Security MVC登录注销示例教程

    Spring Security MVC登录注销示例教程 今天我们将了解Spring Security Login Example.在阅读这篇文章之前,请先阅读我在"Spring 4 Secu ...

  7. SpringSecurity的简单概述以及配置SpringSecurity的默认登录页面

    SpringSecurity的简单概述 是什么:SpringSecurity融合Spring技术栈,提供JavaEE应 用的整体安全解决方案:提供全面的安全服务 有什么用:可以进行身份验证,就是证明你 ...

  8. (二)Spring Security自定义登录成功或失败处理器

    目录 一:创建登录成功处理器 二:创建登录失败处理器 三:添加处理器 三. 项目地址 我们接着上一章 Spring Security最简单的搭建,进行开发 LoginSuccessHandler 和L ...

  9. 7.Spring Security 退出登录

    Spring Security默认的退出登录URL为/logout,退出登录后,Spring Security会做如下处理: 是当前的Sesion失效: 清除与当前用户关联的RememberMe记录: ...

最新文章

  1. 郸城二高2021年高考成绩查询时间,河南高考最高分是谁,2021年河南高考状元名单分数学校...
  2. fastreport 横向分栏_FastReport开发指南
  3. 毕业设计管理系统PHP,asp.net/net/c#毕业论文管理系统-成品
  4. 真牛!打开mysql
  5. linux解压缩6层
  6. 网络收包流程-网络层处理流程ip_rcv(五)
  7. 常见免费邮箱 SMTP 服务地址及端口
  8. [渝粤教育] 北京理工大学 工程热力学 参考 资料
  9. 电容器单位及电容器单位换算
  10. 基于MATLAB的机器人学、机器视觉与控制
  11. 如何给一个App起名字?
  12. Probability|Given UVA - 11181
  13. 使用ctex宏包出现的kpathsea错误
  14. QT学习-超漂亮的软件登录界面模块
  15. Html+JavaScript+Css 二手车价格评估系统设计开发
  16. 美国康奈尔大学BioNB441元胞自动机MATLAB应用
  17. spotify歌曲下载_k表示使用Spotify歌曲功能进行聚类
  18. Python实现undo操作
  19. python练习实例一 互不相同且不重复的数字组合
  20. 影像匹配代码,论文:Remote sensing image matching featured by the optimal entropy classification

热门文章

  1. 聚观早报 | 美国又一家银行要暴雷;腾讯T13技术黄希彤被曝遭裁员
  2. 手机端点击图片放大特效-PhotoSwipe插件
  3. 分享一个免费网站无障碍工具条
  4. 母带混音插件套装-Acon Digital Mastering Suite 1.2.1 WiN-MAC
  5. chatgpt赋能python:Python中的连接符:介绍与应用
  6. Microsoft Office for Mac 2021 (Office 365) 16.55 Universal
  7. Java+SSH水费管理系统(含源码+论文+答辩PPT等)
  8. chrome快速关闭标签页_将Google Chrome的“新标签页”替换为快速拨号
  9. 使用PD协议分析仪调试Type-C PD兼容性
  10. 毕业设计 - 基于SSH码头船只出行及配套货柜码放 管理系统【源码 + 论文】