1 package cn.home1.oss.lib.security.internal;
2
3 import static cn.home1.oss.lib.security.internal.preauth.PreAuthTokenFilter.ATTR_PRINCIPAL;
4 import static cn.home1.oss.lib.security.starter.FormAuthConfiguration.FORM_AUTHENTICATION_ENTRYPOINT;
5 import static org.apache.commons.lang3.StringUtils.isBlank;
6
7 import cn.home1.oss.lib.security.api.GenericUser;
8 import cn.home1.oss.lib.security.api.Security;
9 import cn.home1.oss.lib.security.api.VerifyCodeProvider;
10 import cn.home1.oss.lib.webmvc.api.RequestResolver;
11
12 import lombok.NonNull;
13 import lombok.Setter;
14 import lombok.extern.slf4j.Slf4j;
15
16 import org.springframework.beans.factory.annotation.Autowired;
17 import org.springframework.beans.factory.annotation.Qualifier;
18 import org.springframework.core.env.Environment;
19 import org.springframework.security.authentication.BadCredentialsException;
20 import org.springframework.security.core.AuthenticationException;
21 import org.springframework.security.core.context.SecurityContextHolder;
22 import org.springframework.security.web.AuthenticationEntryPoint;
23 import org.springframework.web.filter.GenericFilterBean;
24
25 import java.io.IOException;
26
27 import javax.servlet.FilterChain;
28 import javax.servlet.ServletException;
29 import javax.servlet.ServletRequest;
30 import javax.servlet.ServletResponse;
31 import javax.servlet.http.HttpServletRequest;
32 import javax.servlet.http.HttpServletResponse;
33
34
35
36
37
38
39
40
41
42 @Setter
43 @Slf4j
44 public class VerifyCodeFilter extends GenericFilterBean {
45
46
47
48
49
50 @Qualifier(FORM_AUTHENTICATION_ENTRYPOINT)
51 @Autowired
52 @NonNull
53 private AuthenticationEntryPoint formAuthenticationEntryPoint;
54
55 @Autowired(required = false)
56 @NonNull
57 private VerifyCodeProvider codeVerifyProvider;
58
59 @Autowired
60 @NonNull
61 private RequestResolver requestResolver;
62
63 @Override
64 public void doFilter(
65 final ServletRequest req, final ServletResponse res, final FilterChain chain
66 ) throws IOException, ServletException {
67 final HttpServletRequest request = (HttpServletRequest) req;
68 final HttpServletResponse response = (HttpServletResponse) res;
69
70 try {
71 if (this.authenticationIsRequired(request)) {
72 final GenericUser principal = (GenericUser) request.getAttribute(ATTR_PRINCIPAL);
73 this.authenticate(request, principal);
74 }
75 } catch (final AuthenticationException failed) {
76 SecurityContextHolder.clearContext();
77
78 if (log.isTraceEnabled()) {
79 log.trace("AUTH authentication failed. not login.", failed);
80 }
81
82 this.formAuthenticationEntryPoint.commence(request, response, failed);
83 return;
84 }
85
86 chain.doFilter(request, response);
87 }
88
89 private boolean authenticationIsRequired(final HttpServletRequest request) {
90
91 return Security.authenticationIsRequired() && this.requestResolver.isLoginRequest(request);
92 }
93
94 private void authenticate(
95 final HttpServletRequest request,
96 final GenericUser principal
97 ) throws AuthenticationException {
98 final String code = request.getParameter("verifycode");
99 if (isBlank(code)) {
100 throw new BadCredentialsException("verifycode is required");
101 }
102 final String uuid = principal.getUuid();
103 final Boolean match = this.codeVerifyProvider.match(uuid, code);
104 if (!match) {
105 throw new BadCredentialsException("verifycode not match");
106 }
107 }
108
109 public String getCodeUrl() {
110 return this.codeVerifyProvider.getCodeUrl();
111 }
112
113 @Autowired
114 @Override
115 public void setEnvironment(final Environment environment) {
116 super.setEnvironment(environment);
117 }
118 }