使用spring security 2.0 和extjs 3.0实现web登录
使用spring security 2.0 和extjs 3.0实现web登录
本例使用MyEclipse 6.5作为开发工具,jdk1.5作为编译工具,tomcat6.0作为web运行服务器。
关于搭建web项目相关的文档网上有很多,在此略过。搭建成功后项目结构如下图
?
?
项目依赖的jar包如下图
?
?
本项目中把index.jsp作为登录页面。代码如下:
?
<%@ taglib prefix='c' uri='http://java.sun.com/jstl/core_rt' %>
<%@ page import="org.springframework.security.ui.AbstractProcessingFilter" %>
<%@ page import="org.springframework.security.ui.webapp.AuthenticationProcessingFilter" %>
<%@ page import="org.springframework.security.AuthenticationException" %>
<c:set var="ctx" value="${pageContext.request.contextPath}"/>
<%
??? String path = request.getContextPath();
??? String basePath = request.getScheme() + "://"
?????????? + request.getServerName() + ":" + request.getServerPort()
?????????? + path + "/";
??? String strLocale = request.getParameter("locale");??
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
? <head>
??? <title>Spring Security + ExtJS Login</title>
???
??? <!-- Ext JS files -->
??? <link rel="stylesheet" type="text/css" href="${ctx}/ext-3.0.0/resources/css/ext-all.css" />
??? <script src="${ctx}/ext-3.0.0/adapter/ext/ext-base.js"></script>
??? <script src="${ctx}/ext-3.0.0/ext-all.js"></script>
??? <!-- login form -->
??? <script src="${ctx}/js/login.js"></script>
???
? </head>
? <body>
? <br><br><br><br><br>
??? <center>
??? <div id="login"></div>
??? </center>
? </body>
</html>
2.2.2 index.jsp源码说明在Index.jsp文件中,代码“<link rel="stylesheet" type="text/css" href="${ctx}/ext-3.0.0/resources/css/ext-all.css" />”是引用extjs的样式。代码“<script src="${ctx}/ext-3.0.0/adapter/ext/ext-base.js"></script>”是加载extjs基本包。
代码“<script src="${ctx}/ext-3.0.0/ext-all.js"></script>”是加载extjs核心包。
代码“<script src="${ctx}/js/login.js"></script>”extjs登录表单。关于login.js的内容,将会在后面小节中介绍。
2.2.3 login.js源码login.js文件中定义的就是extjs登录表单。代码如下:
?
Ext.onReady(function(){
??? Ext.QuickTips.init();
??? var login = new Ext.FormPanel({
?????? labelWidth:80,
?????? url:'j_spring_security_check',
?????? frame:true,
?????? title:'Please Login',
?????? defaultType:'textfield',
?????? width:300,
?????? height:150,
?????? monitorValid:true,
?????? items:[{
?????????? fieldLabel:'Username',
?????????? name:'j_username',
?????????? allowBlank:false
?????? },{
?????????? fieldLabel:'Password',
?????????? name:'j_password',
?????????? inputType:'password',
?????????? allowBlank:false
?????? }],
?????? buttons:[{
?????????? text:'Login',
?????????? formBind: true,
?????????? handler:function(){
?????????? login.getForm().submit({
????????????? method:'POST',
????????????? success:function(){
????????????? Ext.Msg.alert('Status', 'Login Successful!', function(btn, text){
????????????????? if (btn == 'ok'){
???????????????????? window.location = 'main.action';
????????????????? }
????????????? });
?????????? },
?????????? failure:function(form, action){
????????????? if(action.failureType == 'server'){
????????????????? obj = Ext.util.JSON.decode(action.response.responseText);
????????????????? Ext.Msg.alert('Login Failed!', obj.errors.reason);
????????????? }else{
????????????????? Ext.Msg.alert('Warning!', 'Authentication server is unreachable : ' + action.response.responseText);
????????????? }
????????????? login.getForm().reset();
?????????? }
?????????? });
?????? }
?????? }]
??? });
??? login.render('login');
});
2.2.4 index.js源码说明在index.js中定义了一个login表单,url:'j_spring_security_check'对应spring security的登录验证地址。表单里放了两个输入域'j_username'、'j_password',分别对应用户名和密码。表单中还有一个登录按钮'Login',点击按钮提交到后台执行登录验证。验证成功跳转到'main.action',验证失败则提示失败信息。'main.action'是在spring mvc中定义访问地址。具体见2.3节,配置spring mvc.
本项目中的spring mvc用到2个文件,src目录下com.loiane.controller.MainController.java和WEB-INF目录下的spring-security-extjs-login-servlet.xml。
2.3.1 spring-security-extjs-login-servlet.xml源码?
<?xml version="1.0" encoding="UTF-8"?>
?
<beans xmlns="http://www.springframework.org/schema/beans"
?????? xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
?????? xsi:schemaLocation="http://www.springframework.org/schema/beans
?????? http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
?
??? <bean name="/*.action" class="com.loiane.controller.MainController">
??? </bean>
?????
</beans>
2.3.2 spring-security-extjs-login-servlet.xml源码说明spring-security-extjs-login-servlet.xml用于URL地址映射,把类似"/*.action"的请求地址映射到com.loiane.controller.MainController.java控制器类做进一步处理,文件中有一句代码:“<bean name="/*.action" style="margin: 0cm 0cm 0pt;">?
package com.loiane.controller;
?
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;
?
public class MainController extends MultiActionController? {
???????? public ModelAndView main(HttpServletRequest request,
??????????????????????????? HttpServletResponse response) throws Exception {
?????????????????? return new ModelAndView("main.jsp");
???????? }
}
?
?
?
?
?
?
?
?
?
?
?
?
?
?
2.3.4 com.loiane.controller.MainController.java源码说明com.loiane.controller.MainController.java继承
org.springframework.web.servlet.mvc.multiaction.MultiActionController.java类,跳转到main.jsp。
2.3.5 main.jsp源码?
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
??? pageEncoding="ISO-8859-1"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Spring Security + ExtJS Login</title>
</head>
<body>
<h1>You are successfully authenticated!</h1>
</body>
</html>
本项目中的spring security用到2个文件,src目录下com.loiane.security.MyAuthenticationProcessingFilter.java和WEB-INF目录下的applicationContext-security.xml。
2.4.1 applicationContext-security.xml源码?
<?xml version="1.0" encoding="UTF-8"?>
?<beans xmlns="http://www.springframework.org/schema/beans"
??? xmlns:security="http://www.springframework.org/schema/security"
??? xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
??? xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.xsd">
??? <security:global-method-security />
??? <security:http auto-config="false" entry-point-ref="authenticationProcessingFilterEntryPoint">
?????? <security:intercept-url pattern="/index.jsp" filters="none" />
?????? <security:intercept-url pattern="/*.action" access="ROLE_USER" />
??? </security:http>
??? <bean id="authenticationProcessingFilter" class="com.loiane.security.MyAuthenticationProcessingFilter">
?????? <security:custom-filter position="AUTHENTICATION_PROCESSING_FILTER" />
?????? <property name="defaultTargetUrl" value="/main.html" />
?????? <property name="authenticationManager" ref="authenticationManager" />
??? </bean>???
?
?
<security:authentication-manager alias="authenticationManager" />
?
??? <bean id="authenticationProcessingFilterEntryPoint"
??? ??? class="org.springframework.security.ui.webapp.AuthenticationProcessingFilterEntryPoint">
?????? <property name="loginFormUrl" value="/index.jsp" />
?????? <property name="forceHttps" value="false" />
??? </bean>
?
??? <!--
??? Usernames/Passwords are
????? ??admin/111111
??????? dianne/111111
??????? scott/111111
??????? peter/111111
??? These passwords are from spring security app example???
??? -->
??? <security:authentication-provider>
??????? <security:password-encoder hash="md5"/>
??????? <security:user-service>
??????????? <security:user name=" admin " password="96e79218965eb72c92a549dd5a330112" authorities="ROLE_SUPERVISOR, ROLE_USER, ROLE_TELLER" />
??????????? <security:user name="dianne" password="96e79218965eb72c92a549dd5a330112" authorities="ROLE_USER,ROLE_TELLER" />
??????????? <security:user name="scott" password="96e79218965eb72c92a549dd5a330112" authorities="ROLE_USER" />
??????????? <security:user name="peter" password="96e79218965eb72c92a549dd5a330112" authorities="ROLE_USER" />
??? ??? </security:user-service>
??? </security:authentication-provider>
</beans>
2.4.2 applicationContext-security.xml源码说明在applicationContext-security.xml文件中配置登录权限验证。
<security:http auto-config="false" entry-point-ref="authenticationProcessingFilterEntryPoint">
?????? <security:intercept-url pattern="/index.jsp" filters="none" />
?????? <security:intercept-url pattern="/*.action" access="ROLE_USER" />
??? </security:http>
这段配置表示:我们要保护应用程序中的/*.action的URL,只有拥有ROLE_USER角色的用户才能访问。任何角色的用户都可以访问/index.jsp。你可以使用多个<intercept-url>元素为不同URL的集合定义不同的访问需求,它们会被归入一个有序队列中,每次取出最先匹配的一个元素使用。 所以你必须把期望使用的匹配条件放到最上边。entry-point-ref="authenticationProcessingFilterEntryPoint"表示定义一个权限验证的入口authenticationProcessingFilterEntryPoint。
?
<bean id="authenticationProcessingFilter" class="com.loiane.security.MyAuthenticationProcessingFilter">
?????? <security:custom-filter position="AUTHENTICATION_PROCESSING_FILTER" />
?????? <property name="defaultTargetUrl" value="/main.html" />
?????? <property name="authenticationManager" ref="authenticationManager" />
??? </bean>
这段配置定义自定义权限处理过滤器com.loiane.security.MyAuthenticationProcessingFilter,defaultTargetUrl指定验证成功或失败后转向的页面,authenticationManager引用权限管理器。
?
<bean id="authenticationProcessingFilterEntryPoint"? ??? class="org.springframework.security.ui.webapp.AuthenticationProcessingFilterEntryPoint">
?????? <property name="loginFormUrl" value="/index.jsp" />
?????? <property name="forceHttps" value="false" />
??? </bean>
这段配置定义权限验证入口,指定登录页面为/index.jsp,不使用https协议。
?
<security:authentication-provider>
??????? <security:password-encoder hash="md5"/>
??????? <security:user-service>
???? ???????<security:user name="admin" password="96e79218965eb72c92a549dd5a330112" authorities="ROLE_SUPERVISOR, ROLE_USER, ROLE_TELLER" />
??????????? <security:user name="dianne" password="96e79218965eb72c92a549dd5a330112" authorities="ROLE_USER,ROLE_TELLER" />
??????????? <security:user name="scott" password="96e79218965eb72c92a549dd5a330112" authorities="ROLE_USER" />
??????????? <security:user name="peter" password="96e79218965eb72c92a549dd5a330112" authorities="ROLE_USER" />
??? ??? </security:user-service>
??? </security:authentication-provider>
</beans>
这段配置定义了4个用户,密码使用md5加密,admin密码为111111拥有ROLE_SUPERVISOR, ROLE_USER, ROLE_TELLER三个角色、dianne密码为111111拥有ROLE_USER,ROLE_TELLER两个角色、scott密码为111111拥有ROLE_USER角色、peter密码为111111拥有ROLE_USER角色。
2.4.3 com.loiane.security.MyAuthenticationProcessingFilter.java源码?
?
package com.loiane.security;
?
import java.io.IOException;
import java.io.Writer;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import org.springframework.security.Authentication;
import org.springframework.security.AuthenticationException;
import org.springframework.security.ui.webapp.AuthenticationProcessingFilter;
?
public class MyAuthenticationProcessingFilter extends AuthenticationProcessingFilter {
???????? protected void onSuccessfulAuthentication(HttpServletRequest request,
??????????????????????????? HttpServletResponse response, Authentication authResult)
???????? throws IOException {
?????????????????? super.onSuccessfulAuthentication(request, response, authResult);
?????????????????? HttpServletResponseWrapper responseWrapper = new HttpServletResponseWrapper(response);
?????????????????? Writer out = responseWrapper.getWriter();
?????????????????? String targetUrl = determineTargetUrl( request );
?????????????????? out.write("{success:true, targetUrl : \'" + targetUrl + "\'}");
?????????????????? out.close();
???????? }
?
???????? protected void onUnsuccessfulAuthentication( HttpServletRequest request,
??????????????????????????? HttpServletResponse response, AuthenticationException failed )
???????? throws IOException {
?????????????????? HttpServletResponseWrapper responseWrapper = new HttpServletResponseWrapper(response);
?????????????????? Writer out = responseWrapper.getWriter();
?????????????????? out.write("{ success: false, errors: { reason: 'Login failed. Try again.' }}");
?????? ???????? out.close();
???????? }
}
2.4.4 com.loiane.security.MyAuthenticationProcessingFilter.java源码说明com.loiane.security.MyAuthenticationProcessingFilter.java继承于
org.springframework.security.ui.webapp.AuthenticationProcessingFilter.java类,重写了
onSuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, Authentication authResult)和onUnsuccessfulAuthentication( HttpServletRequest request, HttpServletResponse response, AuthenticationException failed )方法。在onSuccessfulAuthentication()方法中返回验证成功后的跳转地址,在onUnsuccessfulAuthentication()方法中返回验证失败的信息。
?
?
?
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
??? <display-name>spring-security-extjs-login</display-name>
??? <context-param>
?????? <param-name>contextConfigLocation</param-name>
?????? <param-value>
?????????? /WEB-INF/spring-security-extjs-login-servlet.xml
?????????? /WEB-INF/applicationContext-security.xml
?????? </param-value>
??? </context-param>
??? <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>
???
??? <listener> ??? <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
??? </listener>
???
??? <servlet>
??? <servlet-name>spring-security-extjs-login</servlet-name>
??? <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
??? <load-on-startup>1</load-on-startup>
? </servlet>
?
? <servlet-mapping>
??? <servlet-name>spring-security-extjs-login</servlet-name>
??? <url-pattern>*.action</url-pattern>
? </servlet-mapping>
?
? <welcome-file-list>
??? <welcome-file>index.jsp</welcome-file>
? </welcome-file-list>
???
</web-app>
?
?
?
?
2.5.1 web.xml源码说明<context-param>
?????? <param-name>contextConfigLocation</param-name>
?????? <param-value>
?????????? /WEB-INF/spring-security-extjs-login-servlet.xml
?????????? /WEB-INF/applicationContext-security.xml
?????? </param-value>
??? </context-param>
??? <filter>
这段代码配置spring使用的相关配置文件。/WEB-INF/spring-security-extjs-login-servlet.xml是关于spring mvc的相关配置。/WEB-INF/applicationContext-security.xml是关于登录权限验证相关的配置。
?
<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>
???
这段代码配置spring过滤链。处理所有URL地址。
?
<listener> ??? <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
??? </listener>
?
这段代码注册spring监听器。
?
<servlet>
??? <servlet-name>spring-security-extjs-login</servlet-name>
??? <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
??? <load-on-startup>1</load-on-startup>
? </servlet>
?
? <servlet-mapping>
??? <servlet-name>spring-security-extjs-login</servlet-name>
??? <url-pattern>*.action</url-pattern>
? </servlet-mapping>
?
这段代码注册spring mvc,处理*.action的请求。
?
?
?
?
?
?
登录页面
?
?
登录页面-验证成功提示
?
?
登录页面-验证成功后跳转到main.jsp页面
??
?
登录页面-验证失败提示
?
?
?
http://loianegroner.com/2010/02/integrating-spring-security-with-extjs-login-page/#comments