我有一个e CaptchaFilter
类,用于在用户登录时检查验证码的值。在spring的xml配置中,我配置如下:
<filter>
<filter-name>CheckCaptchaFilter</filter-name>
<filter-class>org.baharan.cms.common.filters.security.CheckCaptchaFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CheckCaptchaFilter</filter-name>
<url-pattern>/j_spring_security_check</url-pattern>
</filter-mapping>
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
这是登录表单:
<form name="form" action="<c:url value='/j_spring_security_check' />" method='POST'>
<!-- labels and inputs here-->
<c:if test="${sessionScope.LOGIN_ATTEMPTS >= 3}">
<div class="form-group">
<img src="<c:url value = '/j-captcha.jpg' />" id="imgCaptcha" onclick='this.src="<c:url value = '/j-captcha.jpg' />"' />
<input type="text" name="jcaptcha" />
</div>
</c:if>
</form>
这是CaptchaFilter
:
public class CaptchaFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
checkLoginAttempts(request);
if (request.getParameter("jcaptcha") != null) {
checkCaptcha(request, response, filterChain);
}
else {
filterChain.doFilter(request, response);
}
}
private void checkLoginAttempts(HttpServletRequest request) {
HttpSession session = request.getSession();
try {
int loginAttempts = Integer.parseInt(session.getAttribute("LOGIN_ATTEMPTS").toString());
loginAttempts++;
session.setAttribute("LOGIN_ATTEMPTS", loginAttempts);
}
catch (Exception ex) {
session.setAttribute("LOGIN_ATTEMPTS", 1);
}
}
private void checkCaptcha(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException {
try {
String userCaptchaResponse = request.getParameter("jcaptcha");
boolean isResponseCorrect = CaptchaService.getInstance().validateResponseForID(request.getRequestedSessionId(), userCaptchaResponse);
if (isResponseCorrect) {
filterChain.doFilter(request, response);
}
else {
String url = request.getHeader("referer").replaceAll("[&?]error.*?(?=&|\\?|$)", "");
url += "?error=" + SecurityUtility.CAPTCHA_IS_WRONG;
redirect(request, response, url);
}
}
catch (Exception e) {
e.printStackTrace();
filterChain.doFilter(request, response);
}
}
private void redirect(HttpServletRequest request, HttpServletResponse response, String url) {
try {
response.sendRedirect(request.getContextPath() + url);
}
catch (Exception ex) {
ex.printStackTrace();
}
}
@Override
public void destroy() {
}
}
通过这种方式,如果用户输入验证码错误,它会将用户引导至登录页面,而不会调用filterChain.doFilter(request, response);
。
现在,我想在spring java配置中执行此操作,这是我的SpringWebInitializer
类:
public class SpringWebInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(SpringWebConfig.class);
rootContext.register(SpringSecurityConfig.class);
rootContext.register(SpringPersistanceConfig.class);
rootContext.setServletContext(servletContext);
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", new DispatcherServlet(rootContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/", "/rest/*");
FilterRegistration.Dynamic filter = servletContext.addFilter("openSessionInViewFilter", OpenSessionInViewFilter.class);
filter.setInitParameter("sessionFactoryBeanName", "sessionFactory");
filter.addMappingForServletNames(null, true, "dispatcher");
servletContext.addListener(new ContextLoaderListener(rootContext));
}
}
和这个SpringSecurityConfig
类:
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier("userDetailsService")
UserDetailsService userDetailsService;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.headers().frameOptions().sameOrigin();
http.authorizeRequests()
.antMatchers("/assets/**", "/panel/login**","/panel/login.jsp**", "/login**", "/login.jsp**").permitAll()
.antMatchers("/panel/**", "/rest/**").access("hasRole('ROLE_USER')")
.and().formLogin().loginPage("/login")
.failureUrl("/login?error")
.defaultSuccessUrl("/panel")
.usernameParameter("username").passwordParameter("password")
.and().logout().logoutSuccessUrl("/login?logout")
.and().csrf().disable();
}
}
这是BaseController
来显示观点:
@Controller
public class BaseController {
@RequestMapping(value = "/panel**", method = RequestMethod.GET)
public ModelAndView adminPage() {
ModelAndView model = new ModelAndView();
model.setViewName("/panel/admin");
return model;
}
@RequestMapping(value = "/login", method = RequestMethod.GET)
public ModelAndView login() {
ModelAndView model = new ModelAndView();
model.setViewName("/panel/login");
return model;
}
}
我很困惑,我是初次使用java配置的新手,请帮助!!
概念性问题:
这是在春天实施验证码的正确和最佳方式吗?如果没有,请解释正确的方法。