浏览 6517 次
锁定老帖子 主题:扩展acegi以支持验证码等
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (5)
|
|
---|---|
作者 | 正文 |
发表时间:2007-06-22
<form action="<c:url value="j_acegi_security_check"/>" method="POST"> 登陆的请求是发给/ j_acegi_security_check,在我们的系统中往往要在登陆中做一些登陆前和登陆后的操作。如记录用户的行为,加入验证码等。 在acegi的配置文件中加入以下的过滤器: <bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy"> <property name="filterInvocationDefinitionSource"> <value> CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON PATTERN_TYPE_APACHE_ANT /**=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor </value> </property> </bean> 通过改写authenticationProcessingFilter可以实现以上目的: <bean id="authenticationProcessingFilter" class="org.artemis.manager.auth.AuthenticationProcessingFilter"> <property name="authenticationManager" ref="authenticationManager" /> <!-- 认证失败后,重定向的url --> <property name="authenticationFailureUrl" value="/login.jsp?login_error=1" /> <!-- 认证成功后,重定向的url --> <property name="defaultTargetUrl" value="/" /> <!-- 该过滤器拦截的url,通常是/j_acegi_security_check,和登录页面(login.jsp)的登录表单的action相同 --> <property name="filterProcessesUrl" value="/j_acegi_security_check" /> <property name="rememberMeServices" ref="rememberMeServices" /> </bean> package org.artemis.manager.auth; ………………………… public class AuthenticationProcessingFilter implements Filter, InitializingBean, ApplicationEventPublisherAware { public static final String ACEGI_SAVED_REQUEST_KEY = "ACEGI_SAVED_REQUEST_KEY"; public static final String ACEGI_SECURITY_LAST_EXCEPTION_KEY = "ACEGI_SECURITY_LAST_EXCEPTION"; public static final String ACEGI_SECURITY_FORM_USERNAME_KEY = "j_username"; public static final String ACEGI_SECURITY_FORM_PASSWORD_KEY = "j_password"; public static final String ACEGI_SECURITY_LAST_USERNAME_KEY = "ACEGI_SECURITY_LAST_USERNAME"; private ApplicationEventPublisher eventPublisher; private AuthenticationDetailsSource authenticationDetailsSource = new AuthenticationDetailsSourceImpl(); private AuthenticationManager authenticationManager; private String authenticationFailureUrl; private String defaultTargetUrl; private String filterProcessesUrl = getDefaultFilterProcessesUrl(); private boolean alwaysUseDefaultTargetUrl = false; private RememberMeServices rememberMeServices = new NullRememberMeServices(); protected MessageSourceAccessor messages = AcegiMessageSource.getAccessor(); private Properties exceptionMappings = new Properties(); private boolean continueChainBeforeSuccessfulAuthentication = false; public boolean isContinueChainBeforeSuccessfulAuthentication() { return continueChainBeforeSuccessfulAuthentication; } public void setContinueChainBeforeSuccessfulAuthentication( boolean continueChainBeforeSuccessfulAuthentication) { this.continueChainBeforeSuccessfulAuthentication = continueChainBeforeSuccessfulAuthentication; } public String getDefaultFilterProcessesUrl() { return "/j_acegi_security_check"; } public void destroy() {} public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException { if (!(request instanceof HttpServletRequest)) { throw new ServletException("Can only process HttpServletRequest"); } if (!(response instanceof HttpServletResponse)) { throw new ServletException("Can only process HttpServletResponse"); } HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; String username = obtainUsername(httpRequest); String password = obtainPassword(httpRequest); if (username == null) { username = ""; } if (password == null) { password = ""; } if (requiresAuthentication(httpRequest, httpResponse)) { Authentication authResult; try { //加入验证码 if(!onPreAuthentication(httpRequest, httpResponse)){ httpRequest.getSession().setAttribute(ACEGI_SECURITY_LAST_USERNAME_KEY, username); throw new AuthenticationCodeException("请输入正确的验证码!"); } UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password); setDetails(httpRequest, authRequest); httpRequest.getSession().setAttribute(ACEGI_SECURITY_LAST_USERNAME_KEY,username); authResult = this.getAuthenticationManager().authenticate(authRequest); // Authentication success if (continueChainBeforeSuccessfulAuthentication) { filterChain.doFilter(httpRequest, httpResponse); } //可以在此加入验证成功后的功能代码 successfulAuthentication(httpRequest, httpResponse, authResult); String targetUrl = alwaysUseDefaultTargetUrl ? null : obtainFullRequestUrl(httpRequest); if (targetUrl == null) { targetUrl = getDefaultTargetUrl(); } if (!targetUrl.startsWith("http://") && !targetUrl.startsWith("https://")) { targetUrl = httpRequest.getContextPath() + targetUrl; } httpResponse.sendRedirect(httpResponse.encodeRedirectURL(targetUrl)); return ; } catch (AuthenticationException failed) { // Authentication failed unsuccessfulAuthentication(httpRequest, httpResponse, failed); String failureUrl = exceptionMappings.getProperty(failed.getClass().getName(), authenticationFailureUrl); if (!failureUrl.startsWith("http://") && !failureUrl.startsWith("https://")) { failureUrl = httpRequest.getContextPath() + failureUrl; } httpResponse.sendRedirect(httpResponse.encodeRedirectURL(failureUrl)); return; } } filterChain.doFilter(request, response); } public Authentication attemptAuthentication(HttpServletRequest request,HttpServletResponse response) throws AuthenticationException, IOException{ String username = obtainUsername(request); String password = obtainPassword(request); // System.out.println("username: "+username +" passward:"+password) ; if (username == null) { username = ""; } if (password == null) { password = ""; } UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password); setDetails(request, authRequest); request.getSession().setAttribute(ACEGI_SECURITY_LAST_USERNAME_KEY, username); return this.getAuthenticationManager().authenticate(authRequest); } protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) { authRequest.setDetails(new WebAuthenticationDetails(request)); } protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) { String uri = request.getRequestURI(); int pathParamIndex = uri.indexOf(';'); if (pathParamIndex > 0) { uri = uri.substring(0, pathParamIndex); } return uri.endsWith(request.getContextPath() + filterProcessesUrl); } public void init(FilterConfig arg0) throws ServletException {} public void afterPropertiesSet() throws Exception {} public void setApplicationEventPublisher(ApplicationEventPublisher context) { this.eventPublisher = context; } public void setAuthenticationDetailsSource(AuthenticationDetailsSource authenticationDetailsSource) { Assert.notNull(authenticationDetailsSource, "AuthenticationDetailsSource required"); this.authenticationDetailsSource = authenticationDetailsSource; } public boolean isAlwaysUseDefaultTargetUrl() { return alwaysUseDefaultTargetUrl; } public void setAlwaysUseDefaultTargetUrl(boolean alwaysUseDefaultTargetUrl) { this.alwaysUseDefaultTargetUrl = alwaysUseDefaultTargetUrl; } public String getAuthenticationFailureUrl() { return authenticationFailureUrl; } public void setAuthenticationFailureUrl(String authenticationFailureUrl) { this.authenticationFailureUrl = authenticationFailureUrl; } public String getDefaultTargetUrl() { return defaultTargetUrl; } public void setDefaultTargetUrl(String defaultTargetUrl) { this.defaultTargetUrl = defaultTargetUrl; } public String getFilterProcessesUrl() { return filterProcessesUrl; } public void setFilterProcessesUrl(String filterProcessesUrl) { this.filterProcessesUrl = filterProcessesUrl; } protected String obtainPassword(HttpServletRequest request) { String password=request.getParameter(ACEGI_SECURITY_FORM_PASSWORD_KEY); if(password!=null){ return MD5.toMD5(request.getParameter(ACEGI_SECURITY_FORM_PASSWORD_KEY)); } return password; } protected String obtainUsername(HttpServletRequest request) { return request.getParameter(ACEGI_SECURITY_FORM_USERNAME_KEY); } //加入验证码 protected boolean onPreAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException { String randNum=request.getParameter("randNum"); String rand=(String)request.getSession().getAttribute("rand"); if(rand.equals(randNum)){ return true; } return false; } //可以在此加入验证成功后的功能代码 protected void onSuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, Authentication authResult) throws IOException {} protected void onUnsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException {} protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, Authentication authResult) throws IOException { //logger.info("Authentication success: " + authResult.toString()); SecurityContextHolder.getContext().setAuthentication(authResult); onSuccessfulAuthentication(request, response, authResult); rememberMeServices.loginSuccess(request, response, authResult); // Fire event if (this.eventPublisher != null) { eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(authResult, this.getClass())); } } protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException { SecurityContextHolder.getContext().setAuthentication(null); //logger.info("Updated SecurityContextHolder to contain null Authentication"); try { request.getSession().setAttribute(ACEGI_SECURITY_LAST_EXCEPTION_KEY, failed); } catch (Exception ignored) {} onUnsuccessfulAuthentication(request, response, failed); rememberMeServices.loginFail(request, response); } public static String obtainFullRequestUrl(HttpServletRequest request) { SavedRequest savedRequest = (SavedRequest) request.getSession() .getAttribute(ACEGI_SAVED_REQUEST_KEY); return (savedRequest == null) ? null : savedRequest.getFullRequestUrl(); } public Properties getExceptionMappings() { return exceptionMappings; } public void setExceptionMappings(Properties exceptionMappings) { this.exceptionMappings = exceptionMappings; } public MessageSourceAccessor getMessages() { return messages; } public void setMessages(MessageSourceAccessor messages) { this.messages = messages; } public RememberMeServices getRememberMeServices() { return rememberMeServices; } public void setRememberMeServices(RememberMeServices rememberMeServices) { this.rememberMeServices = rememberMeServices; } public ApplicationEventPublisher getEventPublisher() { return eventPublisher; } public void setEventPublisher(ApplicationEventPublisher eventPublisher) { this.eventPublisher = eventPublisher; } public AuthenticationDetailsSource getAuthenticationDetailsSource() { return authenticationDetailsSource; } public AuthenticationManager getAuthenticationManager() { return authenticationManager; } public void setAuthenticationManager(AuthenticationManager authenticationManager) { this.authenticationManager = authenticationManager; } } 如何编写验证码由于篇幅问题在此不多说了。在doFilter方法中我们加入onPreAuthentication,通过比较用户输入的验证码和存在session中的验证码,如果相同才进行下一步的验证操作,否则返回登陆页面做出相应的提示。登陆成功后可以在successfulAuthentication方法中加入一些登陆后操作。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |