默认页面生成
springSecurity过滤器
- DefaultLoginPageGeneratingFilter 生成默认的登录页面
- DefaultLogoutPageGeneratingFilter 生成默认的注销页面
DefaultLoginPageGeneratingFilter
代码语言:javascript复制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中生成登录页面并返回,否则请求继续往下走,执行下一个过滤器。
- 如果当前请求为登录出错请求,注销成功请求或者登录请求,使用generateLoginPageHtml生成登录页面,如果有异常信息一同返回给前端
- 登录页面生成后通过HttpServletResponse将登录页面写回到前端,然后调用return方法跳出过滤器链。
DefaultLogoutPageGeneratingFilter
代码语言:javascript复制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请求,则渲染一个注销请求的页面,否则走下一个过滤器。