这篇文章主要讲解了"春天安全中的默认登录页源码分析",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"春天安全中的默认登录页源码分析"吧!
跳羚项目依赖
属国
groupIdorg.springframework.boot/groupId
artifactIdspring-boot-starter-web/artifactId
/依赖性
属国
groupIdorg.springframework.boot/groupId
artifactId弹簧-启动-启动-安全/artifactId
/依赖性在项目中随意编写一个接口,然后进行访问
@GetMapping('/')
public stringhello(){ 0
回答"你好,春安”;
}在雄猫默认端口8080,localhost:8080下访问该接口春天安全会帮我们将路径重定向到默认的登录页

那么这个默认页是怎么来的呢?
原来春季安全有一个默认的网络安全配置雷达图,发现其中有一个初始化方法,于是在这个方法打了断点,在应用启动的时候进行跟踪。
跟踪getHttp()方法,this.disableDefaults变量默认为假的,意味着将会执行applyDefaultConfiguration(这。http);方法。查看applydedfault配置方法
public void init(WebsecurityWeB)throwsException(
//首先配置安全要拦截的哪些超文本传送协议(超文本传输协议的缩写)请求
httpsecurityHttp=GetHttp();
网络。addsecurityfilterchainbuilder(http).发布构建操作(()-{ 0
filtersecurityintercertorsecurityinterceptor=http。getsharedobject(filtersecurityintertceptor。类);
网络。安全拦截器(security interceptor);
});
}
受保护的finalhttpsecuritygethttp()throwsException {
if(this.http!=null){ 0
returnthis.http
}
authenticationeventpublisher event publisher=Getauthenticationeventpublisher();
这个。localconfigureauthenticationbldr。authenticationeventpublisher(事件发布者);
authenticationmanageruthenticationmanager=authenticationManager();
这个。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中的默认登录页源码分析这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!
内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/76877.html
