Author: Kagula
Date: 2016-10-09
环境
[1]Spring 3.1.2
[2]Tomcat 7.0.68
概要
完美的解决了《学习三》中自定义login方法得绕过Spring Security部份class的缺陷。
最新的例子,解决以下问题
[1]如果login递交的数据,要求验证“验证码”怎么办。
[2]若访问页面没有权限,返回json形式的错误提示。
[3]若login递交的数据非法,返回json形式的错误提示。
[4]若login递交的数据合法,返回json形式的提示。
[5]同个帐号只能同时一次有效,若异地已经登录了这个帐号,会自动把它踢掉。
[6]如何查看登录到Web App的所有用户信息。
也能解决
[1]若已经在其它地方登录的帐户,可以提个醒,你已经把其它地方登录的这个帐号踢掉了。
通过修改MyAuthenticationFilter.java。
[2]若你已经在其它地方登录,不允许再登录。
通过修改spring-security.xml。
正文中会介绍下主要类的功能,然后直接上代码。
《学习二》中未动的代码,这里不重复贴了。
本文的例子在Chrome和Firefox下测试通过。
理解整个Demo建议从spring-security.xml文件开始。
正文
相对于《学习二》这里最重要的是五个java文件,一个配置文件,必须要深刻理解它们之间的关系和功能。
MyAuthenticationEntryPoint.java
当用户没有权限访问某个资源的时候,你可以在这里自定义返回内容。
MyAuthenticationFilter.java
自定义login请求的格式,比如你想上传json格式的请求,可以在这里处理。
并验证用户的请求是否合法,如果不合法你可以抛出继承自AuthenticationException的Exception
MyAuthenticationException.java
继承AuthenticationException,在MyAuthenticationFilter中抛出后,交给MyAuthenticationFailureHandler处理
MyAuthenticationFailureHandler.java
当login失败,这里可以自定义返回的错误信息。
MyAuthenticationSuccessHandler.java
如何登录成功,这里可以自定义返回的成功信息。
配置文件
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="schedule-console" version="3.0">
<display-name>Archetype Created Web Application</display-name>
<!-- 配置字符集过滤器 -->
<!-- 必须配置在所有过滤器的前面 -->
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<!-- 配置项目的编码mapping -->
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 如果同一个bean被定义两次,后面一个优先 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-servlet.xml,/WEB-INF/spring-security.xml</param-value>
</context-param>
<!-- 启动spring容器用,容器用于管理Bean -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Spring Security会话控制 -->
<listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>
<!-- Spring security Filter -->
<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>
<!-- DispatcherServlet 针对MVC上下文加载,即拦截请求,分发请求给Controller -->
<!-- 《ContextLoaderListener初始化的前后文和DispatcherServlet初始化的上下文关系》 http://www.educity.cn/wenda/356953.html -->
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- url-pattern配置为/,不带文件后缀,会造成其它静态文件(js,css等)不能访问。如配为*.do,则不影响静态文件的访问 -->
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<error-page>
<error-code>404</error-code>
<location>/My404.jsp</location>
</error-page>
<error-page>
<exception-type>java.lang.Exception</exception-type>
<location>/MyEception.jsp</location>
</error-page>
</web-app>
spring-security.xml
<?xml version="1.0" encoding="UTF-8"?>
<b:beans xmlns="http://www.springframework.org/schema/security"
xmlns:b="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-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<http pattern="/main/customLogin.do" security=