1 package cn.home1.oss.lib.security.internal.template;
2
3 import static cn.home1.oss.lib.common.CodecUtils.urlEncode;
4
5 import cn.home1.oss.lib.errorhandle.api.ExceptionResolver;
6 import cn.home1.oss.lib.errorhandle.api.ResolvedError;
7 import cn.home1.oss.lib.webmvc.api.TypeSafeCookie;
8
9 import lombok.extern.slf4j.Slf4j;
10
11 import org.springframework.security.core.AuthenticationException;
12 import org.springframework.security.web.DefaultRedirectStrategy;
13 import org.springframework.security.web.RedirectStrategy;
14 import org.springframework.security.web.WebAttributes;
15 import org.springframework.security.web.authentication.AuthenticationFailureHandler;
16 import org.springframework.security.web.util.UrlUtils;
17 import org.springframework.util.Assert;
18
19 import java.io.IOException;
20
21 import javax.servlet.ServletException;
22 import javax.servlet.http.HttpServletRequest;
23 import javax.servlet.http.HttpServletResponse;
24 import javax.servlet.http.HttpSession;
25
26
27
28
29 @Slf4j
30 public class TemplateAuthenticationFailureHandler implements AuthenticationFailureHandler {
31
32
33 private final ExceptionResolver<Throwable> exceptionResolver;
34 private final TypeSafeCookie<ResolvedError> resolvedErrorCookie;
35
36 private String defaultFailureUrl;
37 private boolean forwardToDestination;
38 private boolean allowSessionCreation = true;
39 private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
40
41 public TemplateAuthenticationFailureHandler(
42 final String defaultFailureUrl,
43 final ExceptionResolver<Throwable> exceptionResolver,
44 final TypeSafeCookie<ResolvedError> resolvedErrorCookie
45 ) {
46 this.setDefaultFailureUrl(defaultFailureUrl);
47 this.exceptionResolver = exceptionResolver;
48 this.resolvedErrorCookie = resolvedErrorCookie;
49 }
50
51 @Override
52 public void onAuthenticationFailure(
53 final HttpServletRequest request,
54 final HttpServletResponse response,
55 final AuthenticationException exception
56 ) throws IOException, ServletException {
57 final ResolvedError resolvedError = this.exceptionResolver.resolve(request, exception);
58 if (this.resolvedErrorCookie != null) {
59 this.resolvedErrorCookie.setCookie(request, response, resolvedError.eraseTraces());
60 }
61
62 if (this.defaultFailureUrl == null) {
63 if (log.isDebugEnabled()) {
64 log.debug("No failure URL set, sending 401 Unauthorized error");
65 }
66
67 response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
68 "Authentication Failed: " + exception.getMessage());
69 } else {
70 saveException(request, exception);
71
72 if (this.forwardToDestination) {
73 if (log.isDebugEnabled()) {
74 log.debug("Forwarding to " + this.defaultFailureUrl);
75 }
76
77 request.getRequestDispatcher(this.defaultFailureUrl)
78 .forward(request, response);
79 } else {
80 final String url = this.defaultFailureUrl + "?error=" + urlEncode(resolvedError.getLocalizedMessage());
81 if (log.isDebugEnabled()) {
82 log.debug("Redirecting to " + url);
83 }
84 this.redirectStrategy.sendRedirect(request, response, url);
85 }
86 }
87 }
88
89
90
91
92
93
94
95
96
97
98
99
100
101 protected final void saveException(final HttpServletRequest request, final AuthenticationException exception) {
102 if (this.forwardToDestination) {
103 request.setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, exception);
104 } else {
105 final HttpSession session = request.getSession(false);
106
107 if (session != null || this.allowSessionCreation) {
108 request.getSession().setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, exception);
109 }
110 }
111 }
112
113
114
115
116
117
118 public final void setDefaultFailureUrl(final String defaultFailureUrl) {
119 Assert.isTrue(UrlUtils.isValidRedirectUrl(defaultFailureUrl), "'"
120 + defaultFailureUrl + "' is not a valid redirect URL");
121 this.defaultFailureUrl = defaultFailureUrl;
122 }
123
124 protected boolean isUseForward() {
125 return this.forwardToDestination;
126 }
127
128
129
130
131
132
133
134 public void setUseForward(final boolean forwardToDestination) {
135 this.forwardToDestination = forwardToDestination;
136 }
137
138
139
140
141
142
143 public void setRedirectStrategy(final RedirectStrategy redirectStrategy) {
144 this.redirectStrategy = redirectStrategy;
145 }
146
147 protected RedirectStrategy getRedirectStrategy() {
148 return this.redirectStrategy;
149 }
150
151 protected boolean isAllowSessionCreation() {
152 return this.allowSessionCreation;
153 }
154
155 public void setAllowSessionCreation(final boolean allowSessionCreation) {
156 this.allowSessionCreation = allowSessionCreation;
157 }
158
159 public static TemplateAuthenticationFailureHandler templateFailureHandler(
160 final String loginFormUrl,
161 final ExceptionResolver<Throwable> exceptionResolver,
162 final TypeSafeCookie<ResolvedError> resolvedErrorCookie
163 ) {
164 final TemplateAuthenticationFailureHandler failureHandler = new TemplateAuthenticationFailureHandler(
165 loginFormUrl, exceptionResolver, resolvedErrorCookie);
166 failureHandler.setUseForward(false);
167 failureHandler.setRedirectStrategy(new SmartRedirectStrategy());
168 return failureHandler;
169 }
170 }