1吴青QQ:16910735wuqing_bean@126.com吴老师教学讲义忽然抚尺一下,群响毕绝。撤屏视之,一人、一桌、一椅、一扇、一抚尺而已吴老师教学讲义2Copyright©2010吴青版权所有SpringSecurity3.0什么是SpringSecurity?SpringSecurity,这是一种基于SpringAOP和Servlet过滤器[7]的安全框架。它提供全面的安全性解决方案,同时在Web请求级和方法调用级处理身份确认和授权。在SpringFramework基础上,SpringSecurity充分利用了依赖注入(DI,DependencyInjection)和面向切面技术。获取SpringSecurity3.0吴老师教学讲义3Copyright©2010吴青版权所有解压:dist:目录中存放发布包docs:存放文档入门新建web工程为工程添加Spring支持吴老师教学讲义4Copyright©2010吴青版权所有我这里使用的是MyEclipse6.6版本,该版本中的Spring的版本是Spring2.5,而SpringSecurity3.0使用的是Spring3.0,这里加入Spring支持是为了让工具为我们自动添加Spring的配置文件。SpringSecurity3.0.2下载解压后的dist目录中有两个war包,这两个war包是示例程序将其中的一个示例程序的.war扩展名改成.rar,将其解压出来,将压缩包中的WEB-INF/lib总的所有的jar包拷贝到我们的工程中,在拷贝之前先清除掉MyEclipse帮助我们加入的jar包。吴老师教学讲义5Copyright©2010吴青版权所有添加后的结果:将这些工具帮助我们加入的jar包全部移除掉,然后加入.war中吴老师教学讲义6Copyright©2010吴青版权所有几个包的含义:吴老师教学讲义7Copyright©2010吴青版权所有:包含了核心认证和权限控制类和接口,运程支持和基本供应API。使用SpringSecurity所必须的。支持单独运行的应用,远程客户端,方法(服务层)安全和JDBC用户供应:包含过滤器和对应的web安全架构代码。任何需要依赖servletAPI的。如果需要SpringSecurityWeb认证服务和基于URL的权限控制都需要它开始配置首先配置web.xml文件在web.xml文件中添加一个过滤器,这个过滤器不在security包中.,它可以代理一个applicationcontext中定义的Springbean所实现的filterDelegatingFilterProxy做的事情是代理Filter的方法,从applicationcontext里获得bean(这些bean就是SpringSecurity中的核心部分,过滤器。这些过滤器被定义在了Spring容器中)。这让bean可以获得springwebapplicationcontext的生命周期支持,使吴老师教学讲义8Copyright©2010吴青版权所有配置较为轻便。bean必须实现javax.servlet.Filter接口,它必须和filter-name里定义的名称是一样的。DelegatingFilterProxy这个类在spring-web-3.0.0RELEASE.jar包中吴老师教学讲义9Copyright©2010吴青版权所有1.在web.xml中通过监听器启动spring容器2.在Spring的配置文件中引入SpringSecurity的xml命名空间,这需要修改原来的applicationContext.xml文件.这些代码在下载的文档或者示例应用程序中都能够找到SpringSecurity配置以下的代码都在applicationContext.xml文件中配置吴老师教学讲义10Copyright©2010吴青版权所有这表示,我们要保护应用程序中的所有URL,只有拥有ROLE_USER角色的用户才能访问。http元素是所有web相关的命名空间功能的上级元素。intercept-url元素定义了pattern,用来匹配进入的请求URL,上面的表示拦截根,以及根子目录下的所有的路径。access属性定义了请求匹配了指定模式时的需求。使用默认的配置,这个一般是一个逗号分隔的角色队列,一个用户中的一个必须被允许访问请求。前缀“ROLE_”表示的是一个用户应该拥有的权限比对。上面的配置中只有角色是ROLE_USER的用户才能访问,那么ROLE_USER在哪里定义呢?所以下面的工作就是定义ROLE_USER如果用户名为user,密码为user的用户成功登录了,它的角色是ROLE_USER,那么他可以访问规定的资源。吴老师教学讲义11Copyright©2010吴青版权所有编写首页目前为止,项目中只有一个index.jsp在这个页面上只需要写一句话将项目部署到web服务器中,然后访问首页index.jsp,我们发现首页并没有出现,而是跳转到了一个登录页面上。因为项目刚启动,第一次访问的时候,没有任何用户登录,而在配置文件中我们拦截的是所有的请求,所以第一次请求被拦截了。吴老师教学讲义12Copyright©2010吴青版权所有输入刚才在配置文件中配置的用户名:user,密码:user,提交后,发现能够正确的转到首页问题:那个登录页面哪里来的?当有请求道来的时候,SpringSecurity框架开始检查要访问的资源是否有权访问,如果当前登录用户无权或者当前根本就没有用户登录,则SpringSecurtiy框架就自动产生一个登录页面。当在登录页面进行了正确的登录后,SpringSecurity会自动进行登录验证,如果成功登录,将用户信息放到session中,然后转到先前请求的页面上。我们可以在index中将session中的key—value打印出来,看看SpringSecurity将用户信息如何放到session中的:吴老师教学讲义13Copyright©2010吴青版权所有可以看到:用户使用的key为:SPRING_SECURITY_LAST_USERNAME进阶I在入门部分有明显缺陷:A)一般登录页面都是我们自己编写的,并且登录页面是不需要验证直接可以访问的。B)用户名和密码直接写在配置文件中,而实际项目中我们是放在数据库中的。吴老师教学讲义14Copyright©2010吴青版权所有指定登录页面在前面的例子中,我们在SpringSecurity框架生成的登录页面中直接输入用户名和密码后,SpringSecurity框架替我们进行验证的,那么HTTP请求的时候,向web服务器提交了什么样的数据呢?我们打开生成的登录页面的源代码:由于验证过程是SpringSecurity框架自动完成的,所以在我们的登录页面中表单元素的name都是固定的。下面是我们自己编写的登录页面:login.jsp吴老师教学讲义15Copyright©2010吴青版权所有写完登录页面之后,得让SpringSecurity框架知道哪个页面是登录页面,当需要登录的时候,SpringSecurity框架会自动跳转到这个登录页面上。所以得在applicationContext.xml文件中进行配置启动浏览器访问index.jsp,我们发现自动跳转到login.jsp页面上了。吴老师教学讲义16Copyright©2010吴青版权所有如果输入不正确的用户名或者密码,页面中没有任何错误消息提示,怎么样才能将错误消息显示出来呢?国际化输出SpringSecurity框架将所有的错误信息都定义成了异常,并且提供了国际化的资源文件。这个资源文件在spring-security-core-xxx.jar文件中吴老师教学讲义17Copyright©2010吴青版权所有在配置文件中指定使用的资源文件。这里定义的messageSource对象被springSecurity框架内部使用。在jsp文件中取出错误消息,SpringSecurity框架将抛出的异常对象放到了session范围中,key是:SPRING_SECURITY_LAST_EXCEPTION,取出的是异常对象,所以还要调用getMessage()方法取出真正的错误信息吴老师教学讲义18Copyright©2010吴青版权所有自定义错误消息在src中新建一个message_zh_CN.properties文件吴老师教学讲义19Copyright©2010吴青版权所有在applicationContext.xml中指定资源文件。吴老师教学讲义20Copyright©2010吴青版权所有对密码进行加密上面的配置中,密码以明文的形式出现在了配置文件中,这是非常危险的。所以我们可以将真实密码经过加密之后的结果放到配置文件中。这需要在配置文件中指明使用什么样的加密算法。MD5是一种不可逆的加密算法,验证的时候,将用户输入的密码经过MD5加密之后的结果再与配置文件中配置的密文进行比较,如果相同则通过验证。admin经过MD5加密之后的结果是:21232f297a57a5a743894a0e4a801fc3于是作如下配置:将权限放入数据库保存前面将用户名和密码,还有权限都定义在了配置文件中,而实际项目中需要将这些放到数据数据库中,那么这些信息在数据库中的表结构是什么,能不能自己定义呢?springSecurity将表结构已经定义好了,我们可以参考发行文档中的附录A吴老师教学讲义21Copyright©2010吴青版权所有/*用户表*/createtableusers(usernamevarchar_ignorecase(50)notnullprimarykey,/*用户名*/passwordvarchar_ignorecase(50)notnull,/*密码*/enabledbooleannotnull/*是否禁用*/);/*权限表*/createtableauthorities(usernamevarchar_ignorecase(50)notnull,authorityvarchar_ignorecase(50)notnull,constraintfk_authorities_usersforeignkey(username)referencesusers(username));createuniqueindexix_auth_usernameonauthorities(username,authority);吴老师教学讲义22Copyright©2010吴青版权所有插入数据:INSERTINTOusers(username,PASSWORD,enabled)VALUES('admin','21232f297a57a5a743894a0e4a801fc3',1);/*密码是字符串admin加密后的结果*/INSERTINTOusers(username,PASSWORD,enabled)VALUES('user','ee11cbb19052e40b07aac0ca060c23ee',1);/*密码是字符串user加密后的结果*/INSERTINTOauthoritiesVALUES('admin','ROLE_ADMIN');INSERTINTOauthoritiesVALUES('user','ROLE_USER');吴老师教学讲义23Copyright©2010吴青版权所有·修改配置文件A)在配置文件中加入数据源,因为要访问数据库,所以还要加入MySQL的驱动beanid=datasourceclass=org.springframework.jdbc.datasource.DriverManagerDataSourcepropertyname=driverClassNamevalue=com.mysql.jdbc.Driver/propertyprop