为什么必须用springsecurityjava filterchainn

spring security 3.1配置过程从简单到复杂详细配置
spring security 3.1配置过程从简单到复杂详细配置
[java] &span&style="font-family:&Arial,&Helvetica,&sans-&background-color:&rgb(255,&255,&255);"&废话不多说,直接进入主题。此文章会慢慢跟新。我就在此做一个记录。以后方便自己查阅。&/span&&&
spring security3.1的文档可以去官网下,里面有jar包和说明文档
关于Spring Security3.1的配置网上也很多,但是看看是没有用的,还是需要自己慢慢研究搭环境。
先从最简单的开始说起。
测试项目在:http://download.csdn.net/detail/cctv2505 & &可以下载,测试通过可用。数据库采用mysql。需要的同学可以去看一下。jar包已经配好。
首先我们先把环境搭起来,
我用的是spring mvc+spring securiity3.1,先要配置web.xml文件,
[html] &?xml&version="1.0"&encoding="UTF-8"?&&&&web-app&version="3.0"&&&&&&&xmlns="/xml/ns/javaee"&&&&&&&xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&&&&&&&xsi:schemaLocation="/xml/ns/javaee&&&&&&&/xml/ns/javaee/web-app_3_0.xsd"&&&&&&&&&&&&&&&&&&&&&&&&&&context-param&&&&&&&&&&&&param-name&contextConfigLocation&/param-name&&&&&&&&&&&&param-value&/WEB-INF/security/*.xml&/param-value&&&&&&&&/context-param&&&&&&&&listener&&&&&&&&&&&&listener-class&org.springframework.web.context.ContextLoaderListener&/listener-class&&&&&&&&/listener&&&&&&&&&&&&&&servlet&&&&&&&&&&&&servlet-name&dispatcher&/servlet-name&&&&&&&&&&&&servlet-class&org.springframework.web.servlet.DispatcherServlet&/servlet-class&&&&&&&&&&&&init-param&&&&&&&&&&&&&&&&param-name&contextConfigLocation&/param-name&&&&&&&&&&&&&&&&param-value&/WEB-INF/security/dispatcher-servlet.xml&/param-value&&&&&&&&&&&&/init-param&&&&&&&&&&&&load-on-startup&1&/load-on-startup&&&&&&&&/servlet&&&&&&&&servlet-mapping&&&&&&&&&&&&servlet-name&dispatcher&/servlet-name&&&&&&&&&&&&url-pattern&*.do&/url-pattern&&&&&&&&/servlet-mapping&&&&&!--&权限&--&&&&&&&&&&&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&&&&&&/web-app&&&
spring-security.xml是用来配置security的,dispatcher-servlet.xml是用来配置spring mvc的,
spring mvc的配置很简单,我上面都打了注释。
[html] &?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:mvc="http://www.springframework.org/schema/mvc"&&&&&&&&&xmlns:p="http://www.springframework.org/schema/p"&&&&&&&&&xmlns:context="http://www.springframework.org/schema/context"&&&&&&&&&xmlns:aop="http://www.springframework.org/schema/aop"&&&&&&&&&xmlns:tx="http://www.springframework.org/schema/tx"&&&&&&&&&xsi:schemaLocation="http://www.springframework.org/schema/beans&&&&&&&&&&&&&&http://www.springframework.org/schema/beans/spring-beans-3.0.xsd&&&&&&&&&&&&&&http://www.springframework.org/schema/context&&&&&&&&&&&&&&&http://www.springframework.org/schema/context/spring-context-3.0.xsd&&&&&&&&&&&&&&http://www.springframework.org/schema/aop&&&&&&&&&&&&&&&http://www.springframework.org/schema/aop/spring-aop-3.0.xsd&&&&&&&&&&&&&&http://www.springframework.org/schema/tx&&&&&&&&&&&&&&&http://www.springframework.org/schema/tx/spring-tx-3.0.xsd&&&&&&&&&&&&&&http://www.springframework.org/schema/mvc&&&&&&&&&&&&&&&http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"&&&&&&&&!--&&&&&&&&&使Spring支持自动检测组件,如注解的Controller&&&&&--&&&&&&&&&&&context:component-scan&base-package="com"/&&&&&&&&aop:aspectj-autoproxy/&&&!--&开启AOP&&--&&&&&&&&&&&&&&&&&&&&&bean&id="viewResolver"&&&&&&&&&&&&class="org.springframework.web.servlet.view.InternalResourceViewResolver"&&&&&&&&&&&&p:prefix="/jsp/"&&&&&&&&&&&&p:suffix=".jsp"&&&&&&&&&&&&&/&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&bean&class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"&&&&&&&&&&&&&&&&property&name="messageConverters"&&&&&&&&&&&&&&&&&&&&list&&&&&&&&&&&&&&&&&&&&&&&&&ref&bean="mappingJacksonHttpMessageConverter"&/&&&&&&&&&&&&&&&&&&&&/list&&&&&&&&&&&&&&&&/property&&&&&&&&&&&&/bean&&&&&&&&&&&&&&&&&&&&bean&id="mappingJacksonHttpMessageConverter"&class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"&/&&&&&&&&&&&&!--&数据库连接配置&--&&&&&&&&bean&id="dataSource"&class="com.mchange.boPooledDataSource"&&&&&&&&&&&&property&name="driverClass"&value="com.mysql.jdbc.Driver"&&/property&&&&&&&&&&&&property&name="jdbcUrl"&value="jdbc:mysql://localhost:3306/power"&&/property&&&&&&&&&&&&property&name="user"&value="root"&&/property&&&&&&&&&&&&property&name="password"&value="516725"&&/property&&&&&&&&&&&&property&name="minPoolSize"&value="10"&&/property&&&&&&&&&&&&property&name="MaxPoolSize"&value="50"&&/property&&&&&&&&&&&&property&name="MaxIdleTime"&value="60"&&/property&&!--&最少空闲连接&--&&&&&&&&&&&&property&name="acquireIncrement"&value="5"&&/property&&!--&当连接池中的连接耗尽的时候&c3p0一次同时获取的连接数。&--&&&&&&&&&&&&property&name="TestConnectionOnCheckout"&value="true"&&&/property&&&&&&&&/bean&&&&&&&&bean&id="JdbcTemplate"&class="org.springframework.jdbc.core.JdbcTemplate"&&&&&&&&&&&&property&name="dataSource"&&&&&&&&&&&&&&&&ref&local="dataSource"/&&&&&&&&&&&&/property&&&&&&&&/bean&&&&&&&&!--&事务申明&--&&&&&&&&bean&id="transactionManager"&class="org.springframework.jdbc.datasource.DataSourceTransactionManager"&&&&&&&&&&&&property&name="dataSource"&&&&&&&&&&&&&&&&&ref&local="dataSource"/&&&&&&&&&&&&/property&&&&&&&&/bean&&&&&&&&!--&Aop切入点&--&&&&&&&&aop:config&&&&&&&&&&&&aop:pointcut&expression="within(com.ucs.security.dao.*)"&id="serviceOperaton"/&&&&&&&&&&&&aop:advisor&advice-ref="txadvice"&pointcut-ref="serviceOperaton"/&&&&&&&&/aop:config&&&&&&&&tx:advice&id="txadvice"&transaction-manager="transactionManager"&&&&&&&&&&&&tx:attributes&&&&&&&&&&&&&&&&tx:method&name="delete*"&propagation="REQUIRED"/&&&&&&&&&&&&/tx:attributes&&&&&&&&/tx:advice&&&&/beans&&&
这时候去配置security,我们可以去查阅官方的文档资料。主要的配置在这网页上:
spring-security-3.1.4.RELEASE-dist/spring-security-3.1.4.RELEASE/docs/reference/ns-config.html,在3,。1中我们可以看大下面的基础配置文件
我们可以将第二段段基础配置文件复制到spring-security.xml中,如下
[html] &?xml&version="1.0"&encoding="UTF-8"?&&&&beans:beans&xmlns="http://www.springframework.org/schema/security"&&&&xmlns:beans="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"&&&&&&&/beans:beans&&&&&&
这样环境基本就搭建好了。
硬编码的简单配置
在春天spring-securoty.xml配置文件中添加如下配置:
[html] &!--&对所有页面进行拦截,需要ROLE_USER权限--&&&&&http&auto-config='true'&&&&&&&intercept-url&pattern="/**"&access="ROLE_USER"&/&&&&&/http&&&&&!--&权限配置&jimi拥有两种权限&bob拥有一种权限--&&&&authentication-manager&&&&&&&authentication-provider&&&&&&&&&user-service&&&&&&&&&&&user&name="jimi"&password="123"&authorities="ROLE_USER,&ROLE_ADMIN"&/&&&&&&&&&&&user&name="bob"&password="456"&authorities="ROLE_USER"&/&&&&&&&&&/user-service&&&&&&&/authentication-provider&&&&&/authentication-manager&&&然后基本就可以启动了。security会自动生成登录页面的。http://localhost:8080/spring-security/spring_security_login,这是自动生成的网页代码
他有默认的请求路径和post字段,如果我们自己写登录页面这些都是不能改的。
第二种是通过查数据库来找到用户拥有的权限来控制用户的访问:
建表sql 数据库采用mysql
[sql] CREATE&TABLE&`user`&(&&&&`Id`&int(11)&NOT&NULL&auto_increment,&&&&`logname`&varchar(255)&default&NULL,&&&&`password`&varchar(255)&default&NULL,&&&&`role_ids`&varchar(255)&default&NULL,&&&&PRIMARY&KEY&&(`Id`)&&)&ENGINE=InnoDB&DEFAULT&CHARSET=utf8;&&
修改spring-security.xml文件:
[html] &?xml&version="1.0"&encoding="UTF-8"?&&&&beans:beans&xmlns="http://www.springframework.org/schema/security"&&&&xmlns:beans="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"&&&&&&&&&&!--&启用方法控制访问权限&&用于直接拦截接口上的方法,拥有权限才能访问此方法--&&&&&&&&global-method-security&jsr250-annotations="enabled"/&&&&&&&&!--&自己写登录页面,并且登陆页面不拦截&--&&&&&&&&http&pattern="/jsp/login.jsp"&security="none"&/&&&&&&&&&&&&&&!--&配置拦截页面&&--&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&!--&启用页面级权限控制&使用表达式&--&&&&&&&&http&auto-config='true'&access-denied-page="/jsp/403.jsp"&use-expressions="true"&&&&&&&&&&&&intercept-url&pattern="/**"&access="hasRole('ROLE_USER')"&/&&&&&&&&&&&&!--&设置用户默认登录页面&--&&&&&&&&&&&&form-login&login-page="/jsp/login.jsp"/&&&&&&&&/http&&&&&&&&&&&&&&authentication-manager&&&&&&&&&&&&!--&权限控制&引用&id是myUserDetailsService的server&--&&&&&&&&&&&&authentication-provider&user-service-ref="myUserDetailsService"/&&&&&&&&/authentication-manager&&&&&&&&/beans:beans&&&&
首先编辑自己的登录页面:登录界面中提交的字段必须是security默认的,
[html] &%@&page&language="java"&contentType="text/&charset=utf-8"&&&&&&pageEncoding="utf-8"%&&&&!DOCTYPE&html&PUBLIC&"-//W3C//DTD&HTML&4.01&Transitional//EN"&"http://www.w3.org/TR/html4/loose.dtd"&&&&html&&&&head&&&&meta&http-equiv="Content-Type"&content="text/&charset=utf-8"&&&&title&登录界面&/title&&&&/head&&&&body&&&&&&&&h3&登录界面&/h3&&&&&&&&&&&&&&&&&&form&action="/spring-security/j_spring_security_check"&method="post"&&&&&&&&&&&&&&&&table&&&&&&&&&&&&&&&&&&&&tr&&td&User:&/td&&td&&input&type='text'&name='j_username'&value=''&&/td&&/tr&&&&&&&&&&&&&&&&&&&&tr&&td&Password:&/td&&td&&input&type='password'&name='j_password'/&&/td&&/tr&&&&&&&&&&&&&&&&&&&&tr&&td&colspan='2'&&input&name="submit"&type="submit"&value="Login"/&&/td&&/tr&&&&&&&&&&&&&&&&/table&&&&&&&&&&&&/form&&&&&&&&&&/body&&&&/html&&&
user.jsp页面:user页面是ROLE_USER权限界面,其中引用了security标签,在配置文件中&use-expressions="true"代表启用页面控制语言,就是根据不同的权限页面显示该权限应该显示的内容。如果查看网页源代码也是看不到初自己权限以外的内容的。
[html] &%@&page&language="java"&contentType="text/&charset=utf-8"&pageEncoding="utf-8"%&&&&%@&taglib&prefix="sec"&uri="http://www.springframework.org/security/tags"&%&&&&%@&taglib&prefix="s"&uri="http://www.springframework.org/tags/form"&%&&&&!DOCTYPE&html&PUBLIC&"-//W3C//DTD&HTML&4.01&Transitional//EN"&"http://www.w3.org/TR/html4/loose.dtd"&&&&html&&&&head&&&&meta&http-equiv="Content-Type"&content="text/&utf-8"&&&&title&Insert&title&here&/title&&&&/head&&&&body&&&&&&&&h5&&a&href="../j_spring_security_logout"&logout&/a&&/h5&&&&&&&&!--&拥有ROLE_ADMIN权限的才看的到&--&&&&&&&&sec:authorize&access="hasRole('ROLE_ADMIN')"&&&&&&&&form&action="#"&&&&&&&&&&&账号:&input&type="text"&/&&br/&&&&&&&&&&&密码:&input&type="password"/&&br/&&&&&&&&&&&&input&type="submit"&value="submit"/&&&&&&&&/form&&&&&&&&/sec:authorize&&&&&&&&&&&&&&p/&&&&&&&&sec:authorize&access="hasRole('ROLE_USER')"&&&&&&&显示拥有ROLE_USER权限的页面&br/&&&&&&&&form&action="#"&&&&&&&&&&&账号:&input&type="text"&/&&br/&&&&&&&&&&&密码:&input&type="password"/&&br/&&&&&&&&&&&&input&type="submit"&value="submit"/&&&&&&&&/form&&&&&&&&&&&&&&/sec:authorize&&&&&&&&p/&&&&&&&&h5&测试方法控制访问权限&/h5&&&&&&&&a&href="addreport_admin.do"&添加报表管理员&/a&&br/&&&&&&&&a&href="deletereport_admin.do"&删除报表管理员&/a&&&&/body&&&&/html&&&
Controller层
[java] package&com.ucs.security.&&&&&&import&javax.annotation.R&&import&javax.servlet.http.HttpServletR&&&&import&org.springframework.stereotype.C&&import&org.springframework.web.bind.annotation.RequestM&&import&org.springframework.web.bind.annotation.ResponseB&&import&org.springframework.web.servlet.ModelAndV&&&&import&com.ucs.security.face.SecurityTestI&&&&@Controller&&public&class&SecurityTest&{&&&&&&@Resource&&&&&&private&SecurityTestInterface&&&&&&&&&&&&&@RequestMapping(value="/jsp/getinput")//查看最近收入&&&&&&@ResponseBody&&&&&&public&boolean&getinput(HttpServletRequest&req,HttpServletRequest&res){&&&&&&&&&&boolean&b=dao.getinput();&&&&&&&&&&return&b;&&&&&&}&&&&&&&&&&&&&&&&&&@RequestMapping(value="/jsp/geoutput")//查看最近支出&&&&&&@ResponseBody&&&&&&public&boolean&geoutput(HttpServletRequest&req,HttpServletRequest&res){&&&&&&&&&&boolean&b=dao.geoutput();&&&&&&&&&&return&b;&&&&&&}&&&&&&&&&&&&@RequestMapping(value="/jsp/addreport_admin")//添加报表管理员&&&&&&@ResponseBody&&&&&&public&boolean&addreport_admin(HttpServletRequest&req,HttpServletRequest&res){&&&&&&&&&&boolean&b=dao.addreport_admin();&&&&&&&&&&return&b;&&&&&&}&&&&&&&&&&&&@RequestMapping(value="/jsp/deletereport_admin")//删除报表管理员&&&&&&@ResponseBody&&&&&&public&boolean&deletereport_admin(HttpServletRequest&req,HttpServletRequest&res){&&&&&&&&&&boolean&b=dao.deletereport_admin();&&&&&&&&&&return&b;&&&&&&}&&&&&&&&&&&&@RequestMapping(value="/jsp/user")//普通用户登录&&&&&&public&ModelAndView&user_login(HttpServletRequest&req,HttpServletRequest&res){&&&&&&&&&&dao.user_login();&&&&&&&&&&return&new&ModelAndView("user");&&&&&&}&&&&&&&&}&&
接口: 在配置文件中&global-method-security jsr250-annotations="enabled"/&就是在接口上设置权限,当拥有权限时才能调用方法,没有权限是不能调用方法的,保证了安全性
[java] package&com.ucs.security.&&&&import&javax.annotation.security.RolesA&&&&import&com.ucs.security.pojo.U&&&&public&interface&SecurityTestInterface&{&&&&&&&&boolean&getinput();&&&&&&&&boolean&geoutput();&&&&&&@RolesAllowed("ROLE_ADMIN")//拥有ROLE_ADMIN权限的用户才可进入此方法&&&&&&boolean&addreport_admin();&&&&&&@RolesAllowed("ROLE_ADMIN")&&&&&&boolean&deletereport_admin();&&&&&&&&&&&&Users&findbyUsername(String&name);&&&&&&@RolesAllowed("ROLE_USER")&&&&&&void&user_login();&&&&}&&
实现类 dao
[java] package&com.ucs.security.&&import&java.sql.SQLE&&import&javax.annotation.R&&import&org.apache.log4j.L&&import&org.springframework.jdbc.core.JdbcT&&import&org.springframework.jdbc.core.RowCallbackH&&import&org.springframework.stereotype.R&&import&com.ucs.security.face.SecurityTestI&&import&com.ucs.security.pojo.U&&&&@Repository("SecurityTestDao")&&public&class&SecurityTestDao&implements&SecurityTestInterface{&&&&&&Logger&log=Logger.getLogger(SecurityTestDao.class);&&&&&&&&&&&&@Resource&&&&&&private&JdbcTemplate&jdbcT&&&&&&public&boolean&getinput()&{&&&&&&&&&&("getinput");&&&&&&&&&&return&&&&&&&}&&&&&&&&&&&&public&boolean&geoutput()&{&&&&&&&&&&("geoutput");&&&&&&&&&&return&&&&&&&}&&&&&&&&public&boolean&addreport_admin()&{&&&&&&&&&&("addreport_admin");&&&&&&&&&&return&&&&&&&}&&&&&&&&public&boolean&deletereport_admin()&{&&&&&&&&&&("deletereport_admin");&&&&&&&&&&return&&&&&&&}&&&&&&&&&&public&Users&findbyUsername(String&name)&{&&&&&&&&&&final&Users&users&=&new&Users();&&&&&&&&&&&&jdbcTamplate.query("SELECT&*&FROM&USER&WHERE&logname&=&?",&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&new&Object[]&{name},&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&new&RowCallbackHandler()&{&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&@Override&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&public&void&processRow(java.sql.ResultSet&rs)&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&throws&SQLException&{&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&users.setName(rs.getString("logname"));&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&users.setPassword(rs.getString("password"));&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&users.setRole(rs.getString("role_ids"));&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&});&&&&&&&&&&&&(users.getName()+"&&&&"+users.getPassword()+"&&&&"+users.getRole());&&&&&&&&&&return&&&&&&&}&&&&&&&&&&&&&&&&&&&&&&&&@Override&&&&&&public&void&user_login()&{&&&&&&&&&&("拥有ROLE_USER权限的方法访问:user_login");&&&&&&&&&&&&&&&&}&&&&}&&
下面就是重要的一个类:MyUserDetailsService这个类需要去实现UserDetailsService这个接口;
[java] package&com.ucs.security.&&&&import&java.util.HashS&&import&java.util.S&&&&import&javax.annotation.R&&&&import&org.springframework.security.core.GrantedA&&import&org.springframework.security.core.authority.GrantedAuthorityI&&import&org.springframework.security.core.userdetails.U&&import&org.springframework.security.core.userdetails.UserD&&import&org.springframework.security.core.userdetails.UserDetailsS&&import&org.springframework.security.core.userdetails.UsernameNotFoundE&&import&org.springframework.stereotype.S&&&&import&com.ucs.security.face.SecurityTestI&&import&com.ucs.security.pojo.U&&/**&&*&在spring-security.xml中如果配置了&&*&&authentication-manager&&&&&&&&&&&authentication-provider&user-service-ref="myUserDetailsService"&/&&&&&/authentication-manager&&&*&将会使用这个类进行权限的验证。&&*&&&*&**/&&@Service("myUserDetailsService")&&public&class&MyUserDetailsService&implements&UserDetailsService{&&&&&&@Resource&&&&&&private&SecurityTestInterface&&&&&&&&&//登录验证&&&&&&public&UserDetails&loadUserByUsername(String&name)&&&&&&&&&&&&&&throws&UsernameNotFoundException&{&&&&&&&&&&System.out.println("show&login&name:"+name+"&");&&&&&&&&&&Users&users&=dao.findbyUsername(name);&&&&&&&&&&Set&GrantedAuthority&&grantedAuths=obtionGrantedAuthorities(users);&&&&&&&&&&&&&&&&&&&&boolean&enables&=&&&&&&&&&&&boolean&accountNonExpired&=&&&&&&&&&&&boolean&credentialsNonExpired&=&&&&&&&&&&&boolean&accountNonLocked&=&&&&&&&&&&&//封装成spring&security的user&&&&&&&&&&User&userdetail&=&new&User(users.getName(),&users.getPassword(),&enables,&accountNonExpired,&credentialsNonExpired,&accountNonLocked,&grantedAuths);&&&&&&&&&&return&&&&&&&}&&&&&&//查找用户权限&&&&&&public&Set&GrantedAuthority&&obtionGrantedAuthorities(Users&users){&&&&&&&&&&Set&GrantedAuthority&&authSet=new&HashSet&GrantedAuthority&();&&&&&&&&&&authSet.add(new&GrantedAuthorityImpl(users.getRole()));&&&&&&&&&&return&authS&&&&&&}&&&&}&&登录的时候获取登录的用户名,然后通过数据库去查找该用户拥有的权限将权限增加到Set&GrantedAuthority&中,当然可以加多个权限进去,只要用户拥有其中一个权限就可以登录进来。
然后将从数据库查到的密码和权限设置到security自己的User类中,security会自己去匹配前端发来的密码和用户权限去对比,然后判断用户是否可以登录进来。登录失败还是停留在登录界面。
在user.jsp中测试了用户权限来验证是否可以拦截没有权限用户去访问资源:
点击添加报表管理员或者删除报表管理员时候会跳到403.jsp因为没有权限去访问资源,在接口上我们设置了访问的权限:
[java] @RolesAllowed("ROLE_ADMIN")//拥有ROLE_ADMIN权限的用户才可进入此方法&&&&&&boolean&addreport_admin();&&&&&&@RolesAllowed("ROLE_ADMIN")&&&&&&boolean&deletereport_admin();&&
因为登录进来的用户时ROLE_USER权限的。就被拦截下来。logout是登出,返回到登录界面,并且用户在security中的缓存清掉了。一样会对资源进行拦截。
接下来应该是对访问url进行资源权限管理,
先说说上面的那种方法吧,在接口上加上权限,其实这已经差不多可以在一般的项目中可以使用。作为管理员用户他可以有多种角色,那么他可以在访问ROLE_USER,ROLE_ADMIN的东西,而在接口上没有加上访问权限的,最为公共部分,每个人都可以访问的,访问需要验证的资源就会自动跳转到登录界面,登录后访问没有权限的资源就会提示403,没有权限。基本可以满足项目需求。在spring-security.xml中也就不需要配置,可以让所有的地址同行。这种方法是简单,但是不灵活。如果项目是在做了的时候固定什么用户有什么权限,可以访问哪些方法,那么这种配置时比较简单的,但是如果项目需要后期超级管理员可以更改角色可以访问哪些资源的话,那么这种昂发就不行了。需要用将角色可访问资源链接保存到数据库,可以随时更改。
下面就介绍这种可以修改角色访问资源的灵活配置。用哪种方法还是更具项目需求而定。
需要修改配置文件在http标签里添加custom-filter,添加资源权限控制配置,资源权限控制中涉及到两个类。MyAccessDecisionManager和MySecurityMetadataSource
先写上spring-security.xml的配置文件;
[html] &?xml&version="1.0"&encoding="UTF-8"?&&&&beans:beans&xmlns="http://www.springframework.org/schema/security"&&&&xmlns:beans="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"&&&&&&&&&&&&!--&启用方法控制访问权限&&用于直接拦截接口上的方法,拥有权限才能访问此方法--&&&&&&&&global-method-security&jsr250-annotations="enabled"/&&&&&&&&!--&自己写登录页面,并且登陆页面不拦截&--&&&&&&&&http&pattern="/jsp/login.jsp"&security="none"&/&&&&&&&&&&&&&&!--&配置拦截页面&&--&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&!--&启用页面级权限控制&使用表达式&--&&&&&&&&http&auto-config='true'&access-denied-page="/jsp/403.jsp"&use-expressions="true"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&!--&requires-channel="any"&设置访问类型http或者https&--&&&&&&&&&&&&intercept-url&pattern="/admin/**"&access="hasRole('ROLE_ADMIN')"&requires-channel="any"/&&&&&&&&&&&&&&!--&intercept-url&pattern="/admin/**"&拦截地址的设置有加载先后的顺序,&&&&&&&&&&admin/**在前面请求admin/admin.jsp会先去拿用户验证是否有ROLE_ADMIN权限,有则通过,没有就拦截。如果shi&&&&&&&&&&&pattern="/**"&设置在前面,当前登录的用户有ROLE_USER权限,那么就可以登录到admin/admin.jsp&&&&&&&&&&所以两个配置有先后的。&&&&&&&&&&&--&&&&&&&&&&&&intercept-url&pattern="/**"&access="hasRole('ROLE_USER')"&requires-channel="any"/&&&&&&&&&&&&&&&&&&&&&&&&&!--&设置用户默认登录页面&--&&&&&&&&&&&&form-login&login-page="/jsp/login.jsp"/&&&&&&&&&&&&!--&基于url的权限控制,加载权限资源管理拦截器,如果进行这样的设置,那么&&&&&&&&&&&&intercept-url&pattern="/admin/**"&就可以不进行配置了,会在数据库的资源权限中得到对应。&&&&&&&&&&&对于没有找到资源的权限为null的值就不需要登录才可以查看,相当于public的。可以公共访问&&&&&&&&&&&&--&&&&&&&&&&&&custom-filter&ref="securityFilter"&before="FILTER_SECURITY_INTERCEPTOR"/&&&&&&&&/http&&&&&&&&&&&&&&!--&当基于方法权限控制的时候只需要此配置,在接口上加上权限即可控制方法的调用&&&&&&&authentication-manager&&&&&&&&&&&&authentication-provider&user-service-ref="myUserDetailsService"/&&&&&&&&/authentication-manager&&&&&&&&&--&&&&&&&&&&&&&&&&&&&&!--&资源权限控制&--&&&&&&&&beans:bean&id="securityFilter"&class="com.ucs.security.context.MySecurityFilter"&&&&&&&&&&&&!--&用户拥有的权限&--&&&&&&&&&&&&beans:property&name="authenticationManager"&ref="myAuthenticationManager"&/&&&&&&&&&&&&!--&用户是否拥有所请求资源的权限&--&&&&&&&&&&&&beans:property&name="accessDecisionManager"&ref="myAccessDecisionManager"&/&&&&&&&&&&&&!--&资源与权限对应关系&--&&&&&&&&&&&&beans:property&name="securityMetadataSource"&ref="mySecurityMetadataSource"&/&&&&&&&&/beans:bean&&&&&&&&&&&&&&&&&&&&authentication-manager&alias="myAuthenticationManager"&&&&&&&&&&&&!--&权限控制&引用&id是myUserDetailsService的server&--&&&&&&&&&&&&authentication-provider&user-service-ref="myUserDetailsService"/&&&&&&&&/authentication-manager&&&&/beans:beans&&&&&&&&&&&&&&&
在http标签中添加了:&custom-filter ref="securityFilter" before="FILTER_SECURITY_INTERCEPTOR"/&,用于地址的拦截
MySecurityFilter这个类是拦截中一个主要的类,拦截的时候会先通过这里:
[java] package&com.ucs.security.&&&&import&java.io.IOE&&&&import&javax.annotation.R&&import&javax.servlet.F&&import&javax.servlet.FilterC&&import&javax.servlet.FilterC&&import&javax.servlet.ServletE&&import&javax.servlet.ServletR&&import&javax.servlet.ServletR&&&&import&org.apache.log4j.L&&import&org.springframework.security.access.SecurityMetadataS&&import&org.springframework.security.access.intercept.AbstractSecurityI&&import&org.springframework.security.access.intercept.InterceptorStatusT&&import&org.springframework.security.web.FilterI&&import&org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataS&&&&&&&&public&class&MySecurityFilter&extends&AbstractSecurityInterceptor&implements&Filter&{&&&&&&Logger&log=Logger.getLogger(MySecurityFilter.class);&&&&&&&&&&&&private&FilterInvocationSecurityMetadataSource&securityMetadataS&&&&&&public&SecurityMetadataSource&obtainSecurityMetadataSource()&{&&&&&&&&&&return&this.securityMetadataS&&&&&&}&&&&&&public&FilterInvocationSecurityMetadataSource&getSecurityMetadataSource()&{&&&&&&&&&&return&securityMetadataS&&&&&&}&&&&&&&&public&void&setSecurityMetadataSource(&&&&&&&&&&&&&&FilterInvocationSecurityMetadataSource&securityMetadataSource)&{&&&&&&&&&&this.securityMetadataSource&=&securityMetadataS&&&&&&}&&&&&&&&@Override&&&&&&public&void&destroy()&{&&&&&&&&&&//&TODO&Auto-generated&method&stub&&&&&&&&&&&&&&&&}&&&&&&&&@Override&&&&&&public&void&doFilter(ServletRequest&req,&ServletResponse&res,&&&&&&&&&&&&&&FilterChain&chain)&throws&IOException,&ServletException&{&&&&&&&&&&FilterInvocation&fi=new&FilterInvocation(req,res,chain);&&&&&&&&&&("--------MySecurityFilter--------");&&&&&&&&&&invok(fi);&&&&&&}&&&&&&&&&&&&&&&&private&void&invok(FilterInvocation&fi)&throws&IOException,&ServletException&{&&&&&&&&&&//&object为FilterInvocation对象&&&&&&&&&&//1.获取请求资源的权限&&&&&&&&&&//执行Collection&ConfigAttribute&&attributes&=&SecurityMetadataSource.getAttributes(object);&&&&&&&&&&//2.是否拥有权限&&&&&&&&&&//获取安全主体,可以强制转换为UserDetails的实例&&&&&&&&&&//1)&UserDetails&&&&&&&&&&//&Authentication&authenticated&=&authenticateIfRequired();&&&&&&&&&&//this.accessDecisionManager.decide(authenticated,&object,&attributes);&&&&&&&&&&//用户拥有的权限&&&&&&&&&&//2)&GrantedAuthority&&&&&&&&&&//Collection&GrantedAuthority&&authenticated.getAuthorities()&&&&&&&&&&("用户发送请求!&");&&&&&&&&&&InterceptorStatusToken&token&=&&&&&&&&&&&&&&&&&&&&&token&=&super.beforeInvocation(fi);&&&&&&&&&&&&&&&&&&&&try&{&&&&&&&&&&&&&&fi.getChain().doFilter(fi.getRequest(),&fi.getResponse());&&&&&&&&&&}&finally&{&&&&&&&&&&&&&&super.afterInvocation(token,&null);&&&&&&&&&&}&&&&&&}&&&&&&&&@Override&&&&&&public&void&init(FilterConfig&arg0)&throws&ServletException&{&&&&&&&&&&//&TODO&Auto-generated&method&stub&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&public&Class&?&extends&Object&&getSecureObjectClass()&{&&&&&&&&&&//下面的MyAccessDecisionManager的supports方面必须放回true,否则会提醒类型错误&&&&&&&&&&return&FilterInvocation.&&&&&&}&&&&&&&&&&}&&
MySecurityMetadataSource这个类是查找和匹配所有角色的资源对应关系的,通过访问一个资源,可以得到这个资源的角色,返货给下一个类MyAccessDecisionManager去判断是够可以放行通过验证。
[java] package&com.ucs.security.&&&&import&java.util.ArrayL&&import&java.util.C&&import&java.util.HashM&&import&java.util.I&&import&java.util.L&&import&java.util.M&&import&java.util.S&&import&java.util.Map.E&&&&import&javax.annotation.R&&&&import&org.apache.log4j.L&&import&org.springframework.security.access.ConfigA&&import&org.springframework.security.access.SecurityC&&import&org.springframework.security.web.FilterI&&import&org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataS&&import&org.springframework.stereotype.S&&&&import&com.google.gson.G&&import&com.ucs.security.face.SecurityTestI&&import&com.ucs.security.pojo.URLR&&&&&&&&@Service("mySecurityMetadataSource")&&public&class&MySecurityMetadataSource&implements&FilterInvocationSecurityMetadataSource{&&&&&&//由spring调用&&&&&&Logger&log=Logger.getLogger(MySecurityMetadataSource.class);&&&&&&@Resource&&&&&&private&SecurityTestInterface&&&&&&&private&static&Map&String,&Collection&ConfigAttribute&&&resourceMap&=&&&&&&&&&/*public&MySecurityMetadataSource()&{&&&&&&&&&&&&&&&&&&loadResourceDefine();&&&&&}*/&&&&&&&&&&&&&&public&Collection&ConfigAttribute&&getAllConfigAttributes()&{&&&&&&&&&&//&TODO&Auto-generated&method&stub&&&&&&&&&&return&&&&&&&}&&&&&&&&public&boolean&supports(Class&?&&clazz)&{&&&&&&&&&&//&TODO&Auto-generated&method&stub&&&&&&&&&&return&&&&&&&}&&&&&&//加载所有资源与权限的关系&&&&&&private&void&loadResourceDefine()&{&&&&&&&&&&if(resourceMap&==&null)&{&&&&&&&&&&&&&&resourceMap&=&new&HashMap&String,&Collection&ConfigAttribute&&();&&&&&&&&&&&&&&/*List&String&&resources&;&&&&&&&&&&&&&resources&=&Lists.newArrayList("/jsp/user.do","/jsp/getoutput.do");*/&&&&&&&&&&&&&&List&URLResource&&findResources&=&dao.findResource();&&&&&&&&&&&&&&&&&&&&&&&&&&&&for(URLResource&url_resource:findResources){&&&&&&&&&&&&&&&&&&Collection&ConfigAttribute&&configAttributes&=&new&ArrayList&ConfigAttribute&();&&&&&&&&&&&&&&&&&&ConfigAttribute&configAttribute&=&new&SecurityConfig(url_resource.getRole_Name());&&&&&&&&&&&&&&&&&&for(String&resource:url_resource.getRole_url()){&&&&&&&&&&&&&&&&&&&&&&configAttributes.add(configAttribute);&&&&&&&&&&&&&&&&&&&&&&resourceMap.put(resource,&configAttributes);&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&//以权限名封装为Spring的security&Object&&&&&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&Gson&gson&=new&Gson();&&&&&&&&&&("权限资源对应关系:"+gson.toJson(resourceMap));&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&Set&Entry&String,&Collection&ConfigAttribute&&&&resourceSet&=&resourceMap.entrySet();&&&&&&&&&&Iterator&Entry&String,&Collection&ConfigAttribute&&&&iterator&=&resourceSet.iterator();&&&&&&&&&&&&&&&&}&&&&&&//返回所请求资源所需要的权限&&&&&&public&Collection&ConfigAttribute&&getAttributes(Object&object)&throws&IllegalArgumentException&{&&&&&&&&&&&&&&&&&&&&String&requestUrl&=&((FilterInvocation)&object).getRequestUrl();&&&&&&&&&&("requestUrl&is&"&+&requestUrl);&&&&&&&&&&if(resourceMap&==&null)&{&&&&&&&&&&&&&&loadResourceDefine();&&&&&&&&&&}&&&&&&&&&&("通过资源定位到的权限:"+resourceMap.get(requestUrl));&&&&&&&&&&return&resourceMap.get(requestUrl);&&&&&&}&&&&}&&
MyAccessDecisionManager这个类,就是获取到请求资源的角色后判断用户是否有这个权限可以访问这个资源。如果获取到的角色是null,那就放行通过,这主要是对于那些不需要验证的公共可以访问的方法。就不需要权限了。可以直接访问。
[java] import&java.util.C&&import&java.util.I&&import&org.apache.log4j.L&&import&org.springframework.security.access.AccessDecisionM&&import&org.springframework.security.access.AccessDeniedE&&import&org.springframework.security.access.ConfigA&&import&org.springframework.security.authentication.InsufficientAuthenticationE&&import&org.springframework.security.core.A&&import&org.springframework.security.core.GrantedA&&import&org.springframework.stereotype.S&&@Service("myAccessDecisionManager")&&public&class&MyAccessDecisionManager&implements&AccessDecisionManager{&&&&&&Logger&log=Logger.getLogger(MyAccessDecisionManager.class);&&&&&&@Override&&&&&&public&void&decide(Authentication&authentication,&Object&object,&&&&&&&&&&&&&&Collection&ConfigAttribute&&configAttributes)&throws&AccessDeniedException,&&&&&&&&&&&&&&InsufficientAuthenticationException&{&&&&&&&&&&&&&&//&TODO&Auto-generated&method&stub&&&&&&&&&&//如果对应资源没有找到角色&则放行&&&&&&&&&&&&&&if(configAttributes&==&null){&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&return&;&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&&&&&&&("object&is&a&URL:"+object.toString());&&//object&is&a&URL.&&&&&&&&&&&&&&Iterator&ConfigAttribute&&ite=configAttributes.iterator();&&&&&&&&&&&&&&while(ite.hasNext()){&&&&&&&&&&&&&&&&&&ConfigAttribute&ca=ite.next();&&&&&&&&&&&&&&&&&&String&needRole=ca.getAttribute();&&&&&&&&&&&&&&&&&&for(GrantedAuthority&ga:authentication.getAuthorities()){&&&&&&&&&&&&&&&&&&&&&&if(needRole.equals(ga.getAuthority())){&&//ga&is&user's&role.&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&}&&&&&&&&&&&&&&throw&new&AccessDeniedException("no&right");&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&}&&&&&&&&@Override&&&&&&public&boolean&supports(ConfigAttribute&arg0)&{&&&&&&&&&&//&TODO&Auto-generated&method&stub&&&&&&&&&&return&&&&&&&}&&&&&&&&@Override&&&&&&public&boolean&supports(Class&?&&arg0)&{&&&&&&&&&&//&TODO&Auto-generated&method&stub&&&&&&&&&&return&&&&&&&}&&&&}&&
dao的数据库的查找的代码就补贴出来了。
security的权限控制小总结
首先用户没有登录的时候可以访问一些公共的资源,但是必须把&intercept-url pattern="/**" access="hasRole('ROLE_USER')" requires-channel="any"/& &配置删掉,不拦截,任何资源都可以访问,这样公共资源可以任意访问。
对于需要权限的资源已经在数据库配置,如果去访问会直接跳到登录界面。需要登录。
根据登录用户不同分配到的角色就不一样,根据角色不同来获取该角色可以访问的资源。
拥有ROLE_USER角色用户去访问ROLE_ADMIN的资源会返回到403.jsp页面。拥有ROLE_USER和ROLE_ADMIN角色的用户可以去访问两种角色的资源。公共的资源两种角色都可以访问。
security提供了默认的登出地址。登出后用户在spring中的缓存就清除了。
之前做过基于spring-AOP的url和角色的控制,那时候觉得还不错,能做一些简单的权限控制。学习完security发现security真的是很专业啊。能做复杂的权限控制,还只支持页面上的权限控制。
发表评论:
TA的最新馆藏[转]&

我要回帖

更多关于 filterchain 的文章

 

随机推荐