如今不少企业和开发团队都使用了SSH2(Struts 2 +Spring 2.5 +Hibernate)框架来进行开发, 咱们或许已经习惯了强大的Spring Framework 全局配置管理,不能否认,Sping是一个很优秀的开源框架,可是因为Spring3.0版本后强大的的注解式bean的诞生,Spring MVC框架这匹黑马正悄然杀起,但今天Spring MVC不是主角,今天我和你们分享一个一样隶属于SpringSource 的安全框架——Spring Security, 下面的基于Spring MVC给你们分享一下Spring Security 的使用。虽然对它的接触时间不长,参考了一些网上朋友的作法,但也按照个人理解把这个框架介绍介绍,不是很专业,还请你们不要介意 。
html
咱们知道,Web 应用的安全性包括用户认证(Authentication)和用户受权(Authorization)两个部分。用户认证指的是验证某个用户是否为系统中的合法主体,也就是说用户可否访问该系统。用户受权指的是验证某个用户是否有权限执行某个操做。在一个系统中,不一样用户所具备的权限是不一样的。好比对一个资源来讲,有的用户只能进行读取,而有的用户能够进行修改。通常来讲,系统会为不一样的用户分配不一样的角色,而每一个角色则对应一系列的权限。
java
首先,咱们看web.xml
web
Java代码 spring
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!-- 编码统一最好放最上面,最早加载,防止乱码--> <filter> <filter-name>Set Character Encoding</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> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value><!-- 强制进行转码 --> </init-param> </filter> <filter-mapping> <filter-name>Set Character Encoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 而后接着是SpringSecurity必须的filter 优先配置,让SpringSecurity先加载,防止SpringSecurity拦截失效--> <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> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <!-- spring须要加载的配置文件 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value> WEB-INF/classes/applicationContext.xml, WEB-INF/spring3-servlet.xml, WEB-INF/spring-security.xml </param-value> </context-param> <listener> <listener-class> <!-- 因此,要在web.xml下面配置好监听,让服务器启动时就初始化改类,能够获得request --> org.springframework.web.context.request.RequestContextListener </listener-class> </listener> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 默认所对应的配置文件是WEB-INF下的{servlet-name}-servlet.xml,这里即是:spring3-servlet.xml --> <servlet> <servlet-name>spring3</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>spring3</servlet-name> <!-- 这里能够用 / 但不能用 /* ,拦截了全部请求会致使静态资源没法访问,因此要在spring3-servlet.xml中配置mvc:resources --> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
注释已经写了挺多,仍是稍微解释一下要注意的地方,一个是UTF-8编码转换,这个最好加在最前面,让它先生效,我在调试的时候就出过这种状况,web.xml里的其余配置都正常生效了,可是编码死活不行,一中文就乱码,郁闷了老半天,而后突发奇想,是否是web.xml里先声明的配置先生效,后声明的后生效?接着实践,果真不出我所料,把编码转换加在前面,一切正常。。。。我那个晕。。。
数据库
关于Spirng MVC的就不说了,那些数据访问、业务和控制层那些的东东就自个研究去了吧。。这不是今天的重点。
express
接着是spring-security.xml安全
Java代码 服务器
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:security="http://www.springframework.org/schema/security" 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.0.xsd"> <!-- Spring-Security 的配置 --> <!-- 注意use-expressions=true.表示开启表达式,不然表达式将不可用. see:http://www.family168.com/tutorial/springsecurity3/html/el-access.html --> <security:http auto-config="true" use-expressions="false" access-denied-page="/user/login_failure.html"> <!--容许全部人访问--> <!-- <security:intercept-url pattern="/**" access="permitAll" />--> <!--容许ROLE_ADMIN权限访问--> <security:intercept-url pattern="/user/findAll.html" access="ROLE_ADMIN" /> <!--容许ROLE_ADMIN权限访问--> <security:intercept-url pattern="/user/**" access="ROLE_ADMIN" /> <!--容许ROLE_USER权限访问--> <security:intercept-url pattern="/success.jsp" access="ROLE_USER,ROLE_ADMIN" /> <!--容许IS_AUTHENTICATED_ANONYMOUSLY匿名访问--> <security:intercept-url pattern="/anonymously.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY" /> <!-- filters="none" 不过滤这些资源--> <security:intercept-url pattern="/js/**" filters="none" /> <security:intercept-url pattern="/index.jsp" filters="none" /> <!-- login-page:默认指定的登陆页面. authentication-failure-url:出错后跳转页面. default-target-url:成功登录后跳转页面 --> <security:form-login login-page="/index.jsp" authentication-failure-url="/user/login_failure.html" default-target-url="/success.jsp" /> <!-- invalidate-session:指定在退出系统时是否要销毁Session。logout-success-url:退出系统后转向的URL。logout-url:指定了用于响应退出系统请求的URL。其默认值为:/j_spring_security_logout。 --> <security:logout invalidate-session="true" logout-success-url="/index.jsp" logout-url="/j_spring_security_logout" /> <!-- max-sessions:容许用户账号登陆的次数。范例限制用户只能登陆一次。exception-if-maximum-exceeded: 默认为false,此值表示:用户第二次登陆时,前一次的登陆信息都被清空。当exception-if-maximum-exceeded="true"时系统会拒绝第二次登陆。 --> <security:session-management> <security:concurrency-control error-if-maximum-exceeded="true" max-sessions="1" /> </security:session-management> </security:http> <!-- 指定一个自定义的authentication-manager :customUserDetailsService --> <security:authentication-manager> <security:authentication-provider user-service-ref="customUserDetailsService"> <security:password-encoder ref="passwordEncoder" /> </security:authentication-provider> </security:authentication-manager> <!-- 对密码进行MD5编码 --> <bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" /> <!-- 经过 customUserDetailsService,Spring会控制用户的访问级别. 也能够理解成:之后咱们和数据库操做就是经过customUserDetailsService来进行关联. --> <bean id="customUserDetailsService" class="org.yzsoft.springmvcdemo.util.CustomUserDetailsService" /> <!-- 自定义登录错误提示,能够取出mymessages.properties的国际化消息--> <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> <property name="basename" value="classpath:org/yzsoft/springmvcdemo/mymessages" /> </bean> <bean id="localeResolver" class="org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver" /> </beans>
这个多解释一下,首先
session
Java代码 mvc
<security:intercept-url pattern="/findAll.html" access="hasRole('ROLE_ADMIN')" /> <security:intercept-url pattern="/user/**" access="hasRole('ROLE_ADMIN')" /> <security:intercept-url pattern="/anonymously.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY" />
这个是权限控制,声明了拥有什么权限能够访问哪些资源,这个配置的是有ROLE_ADMIN权限的才能够访问/findAll.html,至于这个ROLE_ADMIN从哪来,呆会再解释。或者像第二句同样配置也能够:拥有ROLE_ADMIN权限的才能够访问/user/下的全部资源,不然都会抛出AccessDeniedException 。
IS_AUTHENTICATED_ANONYMOUSLY就是匿名访问的意思,这个相信都懂的。。。
而后是登录和安全退出
Java代码
<security:form-login login-page="/index.jsp" authentication-failure-url="/user/login_failure.html"default-target-url="/user/findAll.html" /> <security:logout invalidate-session="true" logout-success-url="/index.jsp" logout-url="/user/login_failure.html" />
解释下上面一句,相信看也能看出来了的,login-page:默认指定的登陆页面. authentication-failure-url:出错后跳转页面(包括那些个啥用户名密码错误吖。。啥啥啥的。). default-target-url:成功登录后跳转页面 (这里我直接跳到的控制器去查数据列表)。
接着:invalidate-session:指定在退出系统时是否要销毁Session。logout-success-url:退出系统后转向的URL。logout-url:指定了用于响应退出系统请求的URL。其默认值为:/j_spring_security_logout。
接下来是一个比较不错的功能:是否容许同一用户多处登录
Java代码
<security:session-management> <security:concurrency-control error-if-maximum-exceeded="true" max-sessions="1" /> </security:session-management>
exception-if-maximum-exceeded:
默认为false,此值表示:用户第二次登陆时,前一次的登陆信息都被清空。当error-if-maximum-exceeded="true"时系统会拒绝第二次登陆。
max-sessions:容许用户账号登陆的次数,这里咱们容许一次登录。这里咱们作个实验吧,看看是否是真的生效了,请看图
这里咱们看到,当同一个帐号多处登录时,就会报出Maximum sessions of 1 for this principal exceeded 的错误,固然,正式使用咱们换成mymessages.properties里的咱们自定义的国际化消息,这样人性化一点。