首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

Spring Security 3.0配备

2012-07-08 
Spring Security 3.0配置本文说明和参考:http://panyongzheng.iteye.com/blog/1476079应该注意的扫描顺序:

Spring Security 3.0配置
本文说明和参考:http://panyongzheng.iteye.com/blog/1476079
应该注意的扫描顺序:http://panyongzheng.iteye.com/blog/1477691
几个有用的资料:
spring-security 帮助文档中整理出来的简单记录摘要:http://mislay.iteye.com/blog/411323
在spring security使用方法保护:http://marshal.easymorse.com/archives/1260
SpringSecurity笔记3-Securing Methods:http://springsfeng.iteye.com/blog/1295102

xml被扫描顺序参考: http://sence-qi.iteye.com/blog/1328902
由于服务器启动时的加载配置文件的顺序为web.xml---root-context.xml(Spring的配置文件)---servlet-context.xml(SpringMVC的配置文件),由于root-context.xml配置文件中Controller会先进行扫描装配,但是此时service还没有进行事务增强处理,得到的将是原样的Service(没有经过事务加强处理,故而没有事务处理能力)


先按照http://panyongzheng.iteye.com/blog/1475762这里配置完SpringMVC&Hibernate,在增加spring能力时,同时选择spring security jar,并实现全注解方式。注意:service.impl里面的类,如是要是先回滚,那应该throws RuntimeException。

认证管理的几种方式:

<!-- 权限管理操作 -->      <authentication-manager>          <authentication-provider>              <!--               密码加密方式. 常用的有md5 和 sha.               salt-source:忘记了.. 手头api关了,网速卡就不上网查了. 类似在md5上又加了一层. 放置暴力破解. 追加安全性.              <password-encoder hash="md5">                  <salt-source user-property="username"/>              </password-encoder>               -->               <!-- 注入dataSource验证数据库中的用户名.密码.账号状态.和权限相关; -->              <jdbc-user-service data-source-ref="dataSource"                  users-by-username-query="select username,password,enabled from user where username = ? and enabled = 1"                  authorities-by-username-query="select u.username,r.name from user u join user_role ur on u.uid = ur.uid join role r on r.rid = ur.rid where u.username = ?" />              <!--                  使用固定的用户名和密码及权限来做验证.                   <user-service>                  <user name="admin" password="admin" authorities="ROLE_USER, ROLE_ADMIN" />                  <user name="user" password="user" authorities="ROLE_USER" />                  </user-service>              -->          </authentication-provider>


关于方法保护:
在Service加入方法保护:
1.在XXX-security.xml加入:
<global-method-security secured-annotations="enabled" jsr250-annotations="enabled" pre-post-annotations="enabled"/> 

4.在service.java加入@Secured("ROLE_USER")/多权限:@Secured({"ROLE_USER1","ROLE_USER2"}):
@Override@Transactional(propagation=Propagation.REQUIRED,readOnly=true)@Secured("ROLE_USER")public List<Users> selectUsers()  throws RuntimeException{// TODO Auto-generated method stubreturn usersDAO.selectUsers();}

但是这样的方式,在controller上面不起作用。

为了Controller能使用方法保护功能:
1.解决 java.lang.NoSuchMethodError: org.objectweb.asm.org.objectweb.asm.ClassWriter.加入asm.jar。
2.解决java.lang.NoClassDefFoundError: org/objectweb/asm/Type,删除cglib-2.2.jar,加入cglib-nodep-2.2.jar。
3.在XXX-servlet.xml加入
<beans ......    xmlns:security="http://www.springframework.org/schema/security"     xsi:schemaLocation=" ......    http://www.springframework.org/schema/security      http://www.springframework.org/schema/security/spring-security-3.0.xsd">............<security:global-method-security secured-annotations="enabled" jsr250-annotations="enabled" pre-post-annotations="enabled"/> 

4.在Controller.java加入@Secured("ROLE_USER")/多权限:@Secured({"ROLE_USER1","ROLE_USER2"}):
@SuppressWarnings("unchecked")@RequestMapping(value="/saveAndSearch.do")@Secured("ROLE_USER")public ModelAndView search(){    ModelAndView view = new ModelAndView("list");        Users users = new Users();    users.setName("Pandy");    users.setPassword("password");    //helloService.insertUsers(users);        List<Users> list = helloService.selectUsers();    System.out.println("list.size()="+list.size());        view.addObject("message","Search Successful!   counter="+list.size());    return view;    }

但是这样的方式,在Service上面不起作用。

如想两个地方都起作用,那么必须在XXX-secueity.xml和XXX-servlet.xml都加入。都要解决上面的问题就可以了。


源码:
1.数据库:附件有数据库的sql文件;
     1)用户表
DROP TABLE IF EXISTS `users`;CREATE TABLE `users` (  `id` int(10) NOT NULL AUTO_INCREMENT,  `name` varchar(20) DEFAULT NULL,  `password` varchar(20) DEFAULT NULL,  `email` varchar(30) DEFAULT NULL,  PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

     2)角色表
DROP TABLE IF EXISTS `roles`;  CREATE TABLE `roles` (    `id` int(10) NOT NULL auto_increment,    `name` varchar(20) default NULL,    PRIMARY KEY  (`id`)  ) ENGINE=InnoDB DEFAULT CHARSET=utf8;  

     3)权限表
DROP TABLE IF EXISTS `authorities`;CREATE TABLE `authorities` (  `id` int(10) NOT NULL AUTO_INCREMENT,  `description` varchar(100) DEFAULT NULL,  `url` varchar(100) DEFAULT NULL,  PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8; 

     4)用户-角色表
Sql代码 
DROP TABLE IF EXISTS `users_roles`;  CREATE TABLE `users_roles` (    `user_id` int(10) NOT NULL,    `role_id` int(10) NOT NULL,    PRIMARY KEY  (`user_id`,`role_id`),    KEY `FK_R_2` (`role_id`),    CONSTRAINT `FK_R_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`),    CONSTRAINT `FK_R_2` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`)  


    5)角色-权限表
DROP TABLE IF EXISTS `roles_authorities`;  CREATE TABLE `roles_authorities` (    `role_id` int(10) NOT NULL,    `authority_id` int(10) NOT NULL,    PRIMARY KEY  (`role_id`,`authority_id`),    KEY `FK_R_4` (`authority_id`),    CONSTRAINT `FK_R_3` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`),    CONSTRAINT `FK_R_4` FOREIGN KEY (`authority_id`) REFERENCES `authorities` (`id`)  ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 


2.引用的jar见源码。

3.web和spring配置文件
web.xml
<?xml version="1.0" encoding="UTF-8"?><web-app version="3.0" 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_3_0.xsd">  <display-name></display-name>  <context-param><param-name>contextConfigLocation</param-name><param-value>classpath*:applicationContext.xml</param-value></context-param><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><servlet>          <servlet-name>SpringMVCSecurityDemo</servlet-name>          <servlet-class>              org.springframework.web.servlet.DispatcherServlet          </servlet-class>          <load-on-startup>1</load-on-startup>      </servlet>      <servlet-mapping>          <servlet-name>SpringMVCSecurityDemo</servlet-name>          <url-pattern>*.do</url-pattern>      </servlet-mapping>        <!-- SpringSecurity 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>    <welcome-file-list>    <welcome-file>index.jsp</welcome-file>  </welcome-file-list></web-app>




SpringMVCSecurityDemo-servlet.xml
<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"      xmlns:context="http://www.springframework.org/schema/context"        xmlns:mvc="http://www.springframework.org/schema/mvc"      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/mvc        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd    http://www.springframework.org/schema/security      http://www.springframework.org/schema/security/spring-security-3.0.xsd"><!-- 这里启动Controller层方法保护 -->    <security:global-method-security secured-annotations="enabled" jsr250-annotations="enabled" pre-post-annotations="enabled"/>         <mvc:annotation-driven />      <!-- 这里只扫描Controller -->    <context:component-scan base-package="com" use-default-filters="false" > <context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/> </context:component-scan>           <bean value="/pages/"></property><property name="suffix" value=".jsp"></property></bean></beans>


applicationContext.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" xmlns:context="http://www.springframework.org/schema/context"xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jdbc="http://www.springframework.org/schema/jdbc"xmlns:p="http://www.springframework.org/schema/p"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/tx           http://www.springframework.org/schema/tx/spring-tx-3.0.xsd           http://www.springframework.org/schema/jdbc           http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd"default-autowire="byName" default-lazy-init="true"><!-- 这里只扫描Service --><context:component-scan base-package="com" > <context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/> </context:component-scan> <bean id="dataSource" value="com.mysql.jdbc.Driver"></property><property name="url" value="jdbc:mysql://localhost:3306/test"></property><property name="username" value="root"></property></bean><bean id="sessionFactory"/></property><property name="hibernateProperties"><props><prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop></props></property></bean><bean id="transactionManager"/></property></bean><bean id="webApplicationUtils" lazy-init="false"/><tx:annotation-driven transaction-manager="transactionManager" /><import resource="applicationContext-security.xml"/></beans>


4.pojo是通过myeclipse自动生成,这些不给出代码,附件包含所有代码。
5.WebApplicationUtils类
package com.common;import javax.servlet.ServletContext;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.springframework.beans.BeansException;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;import org.springframework.web.context.ServletContextAware;/* * 当我们无法拿到bean的时候,可以通过这样的方式反注入得到WebApplicationContext,然后在getBean(); */public class WebApplicationUtils implements ApplicationContextAware,ServletContextAware{public static ApplicationContext applicationContext = null;public static ServletContext servletContext = null;private static SessionFactory factory;private static Session session;public static  SessionFactory getFactory() {factory = (SessionFactory)WebApplicationUtils.getApplicationContext().getBean("sessionFactory");return factory;}public static  Session getSession() {session = getFactory().getCurrentSession();return session;}public void setApplicationContext(ApplicationContext actx) throws BeansException {if(WebApplicationUtils.applicationContext==null){WebApplicationUtils.applicationContext = actx;}}public void setServletContext(ServletContext sctx) {if(WebApplicationUtils.servletContext==null){WebApplicationUtils.servletContext=sctx;}}public static ApplicationContext getApplicationContext() {return applicationContext;}public static ServletContext getServletContext() {return servletContext;}}


6.三个DAO(接口的定义代码不给出,见附件)
AuthoritiesDAO.java
package com.dao.impl;import java.util.ArrayList;import java.util.Collection;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map;import org.hibernate.SessionFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.orm.hibernate3.support.HibernateDaoSupport;import org.springframework.security.access.ConfigAttribute;import org.springframework.security.access.SecurityConfig;import org.springframework.stereotype.Repository;import com.dao.IAuthoritiesDAO;import com.pojo.Authorities;import com.pojo.RolesAuthorities;@Repositorypublic class AuthoritiesDAO extends HibernateDaoSupport implements IAuthoritiesDAO {@Autowired      public void setSessionFactoryOverride(SessionFactory sessionFactory)     {         super.setSessionFactory(sessionFactory);       }@Overridepublic Map<String, Collection<ConfigAttribute>> getResourceMap() {Map<String, Collection<ConfigAttribute>> resourceMap = new HashMap<String, Collection<ConfigAttribute>>();/*Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();ConfigAttribute adminCA = new SecurityConfig("ROLE_ADMIN");atts.add(adminCA);ConfigAttribute userCA =  new SecurityConfig("ROLE_USER");atts.add(userCA);resourceMap.put("/index.jsp", atts);*/List<Authorities>  list = getAll();for(Authorities auth : list){Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();String url = auth.getUrl();System.out.println("URL="+url);if(auth.getRolesAuthoritieses()!=null){Iterator it = auth.getRolesAuthoritieses().iterator();while(it.hasNext()){RolesAuthorities ra = (RolesAuthorities)it.next();String rolesName = ra.getRoles().getName();ConfigAttribute ca = new SecurityConfig(rolesName);atts.add(ca);System.out.println("rolesName="+rolesName);}}resourceMap.put(url, atts);System.out.println("---------------------------------------");}return resourceMap;}public List<Authorities> getAll(){String hql="from com.pojo.Authorities";List<Authorities>  list = getHibernateTemplate().find(hql);return list;}}



RolesDAO.java
package com.dao.impl;import java.util.List;import org.hibernate.SessionFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.orm.hibernate3.support.HibernateDaoSupport;import org.springframework.stereotype.Repository;import com.dao.IRolesDAO;import com.pojo.Roles;@Repositorypublic class RolesDAO extends HibernateDaoSupport implements IRolesDAO {@Autowired      public void setSessionFactoryOverride(SessionFactory sessionFactory)     {         super.setSessionFactory(sessionFactory);       }@Overridepublic Roles getRolesById(Integer id) {// TODO Auto-generated method stubString hql="from com.pojo.Roles a where a.id=?";List<Roles> list = getHibernateTemplate().find(hql,new Integer[]{id});if(list!=null&&list.size()>0) return list.get(0);return null;}}



UsersDAO.java
package com.dao.impl;import java.util.List;import org.hibernate.SessionFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.orm.hibernate3.support.HibernateDaoSupport;import org.springframework.stereotype.Repository;import com.dao.IUsersDAO;import com.pojo.Roles;import com.pojo.Users;@Repositorypublic class UsersDAO extends HibernateDaoSupport implements IUsersDAO {@Autowired      public void setSessionFactoryOverride(SessionFactory sessionFactory)     {         super.setSessionFactory(sessionFactory);       }@Overridepublic void insertUsers(Users users) {// TODO Auto-generated method stubgetHibernateTemplate().saveOrUpdate(users);}@Override@SuppressWarnings("unchecked")public List<Users> selectUsers() {// TODO Auto-generated method stubString sql = "From com.pojo.Users Order By id";List<Users> list = getHibernateTemplate().find(sql);return list;}@Overridepublic Users getUserByUserName(String username) {// TODO Auto-generated method stubSystem.out.println("@@@@@@@@@getUserByUserName");String sql = "From com.pojo.Users where name=? Order By id";List<Users> list = getHibernateTemplate().find(sql,new String[]{username});if(list!=null&&list.size()>0) return list.get(0);return null;}}



7.三个security用到的service和一个测试业务的controller,service(接口的定义见附件)
HelloController.java
package com.controller;import java.util.List;import javax.annotation.Resource;import javax.annotation.security.RolesAllowed;import org.springframework.security.access.annotation.Secured;import org.springframework.security.access.prepost.PreAuthorize;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.servlet.ModelAndView;import com.pojo.Users;import com.service.IHelloService;@Controllerpublic class HelloController {private String viewName;@Resource(name="helloService")    private IHelloService helloService;        public String getViewName() {return viewName;}public void setViewName(String viewName) {this.viewName = viewName;}    @SuppressWarnings("unchecked")@RequestMapping(value="/saveAndSearch.do")public ModelAndView search(){    ModelAndView view = new ModelAndView("list");        Users users = new Users();    users.setName("Pandy");    users.setPassword("password");    //helloService.insertUsers(users);        List<Users> list = helloService.selectUsers();    System.out.println("list.size()="+list.size());        view.addObject("message","Search Successful!   counter="+list.size());    return view;    }@SuppressWarnings("unchecked")@RequestMapping(value="/search1.do")@Secured("ROLE_USER")public ModelAndView search1(){    ModelAndView view = new ModelAndView("list");    List<Users> list = helloService.selectUsers();    view.addObject("message","Search Successful!   counter="+list.size());    return view;    }@SuppressWarnings("unchecked")@RequestMapping(value="/search2.do")@RolesAllowed("ROLE_ADMIN")public ModelAndView search2(){    ModelAndView view = new ModelAndView("list");    List<Users> list = helloService.selectUsers();    view.addObject("message","Search Successful!   counter="+list.size());    return view;    }@SuppressWarnings("unchecked")@RequestMapping(value="/search3.do")@PreAuthorize("hasRole('ROLE_ADMIN')")public ModelAndView search3(){    ModelAndView view = new ModelAndView("list");    List<Users> list = helloService.selectUsers();    view.addObject("message","Search Successful!   counter="+list.size());    return view;    }}



HelloService.java
package com.service.impl;import java.util.List;import javax.annotation.Resource;import javax.annotation.security.RolesAllowed;import org.springframework.security.access.annotation.Secured;import org.springframework.security.access.prepost.PreAuthorize;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Propagation;import org.springframework.transaction.annotation.Transactional;import com.dao.IUsersDAO;import com.pojo.Users;import com.service.IHelloService;@Service@Transactionalpublic class HelloService implements IHelloService {@Resource(name="usersDAO")public IUsersDAO usersDAO;@Override@Transactional(propagation=Propagation.REQUIRED)public void insertUsers(Users users)  throws RuntimeException{usersDAO.insertUsers(users);}@Override@Transactional(propagation=Propagation.REQUIRED,readOnly=true)public List<Users> selectUsers()  throws RuntimeException{// TODO Auto-generated method stubreturn usersDAO.selectUsers();}@Override@Transactional(propagation=Propagation.REQUIRED,readOnly=true)@Secured("ROLE_USER")public List<Users> selectUsers1()  throws RuntimeException{// TODO Auto-generated method stubreturn usersDAO.selectUsers();}@Override@Transactional(propagation=Propagation.REQUIRED,readOnly=true)@RolesAllowed("ROLE_ADMIN")public List<Users> selectUsers2()  throws RuntimeException{// TODO Auto-generated method stubreturn usersDAO.selectUsers();}@Override@Transactional(propagation=Propagation.REQUIRED,readOnly=true)@PreAuthorize("hasRole('ROLE_ADMIN')")public List<Users> selectUsers3()  throws RuntimeException{// TODO Auto-generated method stubreturn usersDAO.selectUsers();}}



AuthoritiesService.java
package com.service.impl;import java.util.Collection;import java.util.Map;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.security.access.ConfigAttribute;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Transactional;import com.dao.IAuthoritiesDAO;import com.service.IAuthoritiesService;@Service@Transactionalpublic class AuthoritiesService implements IAuthoritiesService {@Autowiredpublic IAuthoritiesDAO authoritiesDAO;@Overridepublic Map<String, Collection<ConfigAttribute>> getResourceMap() {// TODO Auto-generated method stubreturn authoritiesDAO.getResourceMap();}}



RolesService.java
package com.service.impl;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Propagation;import org.springframework.transaction.annotation.Transactional;import com.dao.IRolesDAO;import com.pojo.Roles;import com.service.IRolesService;@Service@Transactionalpublic class RolesService implements IRolesService {@Autowiredpublic IRolesDAO rolesDAO;@Override@Transactional(propagation=Propagation.REQUIRED,readOnly=true)public Roles getRolesById(Integer id) {// TODO Auto-generated method stubreturn rolesDAO.getRolesById(id);}}


UsersService.java
package com.service.impl;import org.hibernate.Hibernate;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Propagation;import org.springframework.transaction.annotation.Transactional;import com.dao.IUsersDAO;import com.pojo.Users;import com.service.IUsersService;@Service@Transactionalpublic class UsersService implements IUsersService {@Autowiredpublic IUsersDAO usersDAO;@Override@Transactional(propagation=Propagation.REQUIRED,readOnly=true)public Users getUserByUserName(String username) {Users user = usersDAO.getUserByUserName(username);Hibernate.initialize(user.getUsersRoleses());return user;}}


8.跟Security相关的四个类,例子最核心的类。
MyInvocationSecurityMetadataSource.java[好像是载入spring applicationcontext.xml之前执行]
package com.security;import java.util.Collection;import java.util.Iterator;import java.util.Map;import org.springframework.security.access.ConfigAttribute;import org.springframework.security.web.FilterInvocation;import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;import org.springframework.security.web.util.AntUrlPathMatcher;import org.springframework.security.web.util.UrlMatcher;import com.common.WebApplicationUtils;import com.service.IAuthoritiesService;/** * 此类在初始化时,应该取到所有资源及其对应角色的定义 */// <!-- 资源源数据定义,即定义某一资源可以被哪些角色访问 -->public class MyInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {private UrlMatcher urlMatcher = new AntUrlPathMatcher();;private static Map<String, Collection<ConfigAttribute>> resourceMap = null;public MyInvocationSecurityMetadataSource() {loadResourceDefine();}private void loadResourceDefine() {/*这里移动到DAO里面,信息从DB获取。  resourceMap = new HashMap<String, Collection<ConfigAttribute>>();Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();ConfigAttribute adminCA = new SecurityConfig("ROLE_ADMIN");atts.add(adminCA);ConfigAttribute userCA =  new SecurityConfig("ROLE_USER");atts.add(userCA);resourceMap.put("/index.jsp", atts);*///resourceMap = authoritiesService.getResourceMap();//不明白这里怎么无法注入,难道因为这个filter在spring之前?????????IAuthoritiesService authoritiesService = (IAuthoritiesService)WebApplicationUtils.getApplicationContext().getBean("authoritiesService");resourceMap = authoritiesService.getResourceMap();System.out.println("-----> 载入资源:loadResourceDefine()");}// According to a URL, Find out permission configuration of this URL.public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {System.out.println("-----> 获得资源:getAttributes()");// guess object is a URL.String url = ((FilterInvocation) object).getRequestUrl();Iterator<String> ite = resourceMap.keySet().iterator();while (ite.hasNext()) {String resURL = ite.next();if (urlMatcher.pathMatchesUrl(url, resURL)) {return resourceMap.get(resURL);}}return null;}public boolean supports(Class<?> clazz) {return true;}public Collection<ConfigAttribute> getAllConfigAttributes() {return null;}}


MyAccessDecisionManager.java
package com.security;import java.util.Collection;import java.util.Iterator;import org.springframework.security.access.AccessDecisionManager;import org.springframework.security.access.AccessDeniedException;import org.springframework.security.access.ConfigAttribute;import org.springframework.security.access.SecurityConfig;import org.springframework.security.authentication.InsufficientAuthenticationException;import org.springframework.security.core.Authentication;import org.springframework.security.core.GrantedAuthority;//<!-- 访问决策器,决定某个用户具有的角色,是否有足够的权限去访问某个资源 -->public class MyAccessDecisionManager implements AccessDecisionManager {// In this method, need to compare authentication with configAttributes.// 1, A object is a URL, a filter was find permission configuration by this// URL, and pass to here.// 2, Check authentication has attribute in permission configuration// (configAttributes)// 3, If not match corresponding authentication, throw a// AccessDeniedException.public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {System.out.println("-----> 访问决策器,决定某个用户具有的角色," +"是否有足够的权限去访问某个资源["+object.toString()+"]");if (configAttributes == null) {return;}System.out.println("被访问资源URL="+object.toString()); // object is a URL.// configAttributes是含有访问url的所有权限// authentication.getAuthorities()用户的权限或者角色Iterator<ConfigAttribute> ite = configAttributes.iterator();while (ite.hasNext()) {ConfigAttribute ca = ite.next();String needRole = ((SecurityConfig) ca).getAttribute();//当url的所需权限,也是这个账户拥有的权限一样的时候,表示有权限,并返回。for (GrantedAuthority ga : authentication.getAuthorities()) {if (needRole.equals(ga.getAuthority())) { // ga is user's role.System.out.println("-----> 有访问权限,返回.");return;}}}//没有权限就抛出异常.throw new AccessDeniedException("没有访问权限.");}@Overridepublic boolean supports(ConfigAttribute attribute) {// TODO Auto-generated method stubreturn true;}@Overridepublic boolean supports(Class<?> clazz) {return true;}}



MyFilterSecurityInterceptor.java
package com.security;import java.io.IOException;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import org.springframework.security.access.SecurityMetadataSource;import org.springframework.security.access.intercept.AbstractSecurityInterceptor;import org.springframework.security.access.intercept.InterceptorStatusToken;import org.springframework.security.web.FilterInvocation;import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;/*<!-- 一个自定义的filter, 必须包含authenticationManager,accessDecisionManager,securityMetadataSource三个属性,   我们的所有控制将在这三个类中实现,解释详见具体配置 --> */public class MyFilterSecurityInterceptor extends AbstractSecurityInterceptorimplements Filter {private FilterInvocationSecurityMetadataSource securityMetadataSource;/** * Method that is actually called by the filter chain. Simply delegates to * the {@link #invoke(FilterInvocation)} method. *  * @param request, the servlet request * @param response, the servlet response * @param chain, the filter chain *  * @throws IOException, if the filter chain fails * @throws ServletException,if the filter chain fails */public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {System.out.println("-----> 自定义的filter.doFilter()");FilterInvocation fi = new FilterInvocation(request, response, chain);invoke(fi);}public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {return this.securityMetadataSource;}public Class<? extends Object> getSecureObjectClass() {return FilterInvocation.class;}public void invoke(FilterInvocation fi) throws IOException, ServletException {System.out.println("-----> 自定义的filter.invoke()");InterceptorStatusToken token = super.beforeInvocation(fi);try {fi.getChain().doFilter(fi.getRequest(), fi.getResponse());} finally {super.afterInvocation(token, null);}}public SecurityMetadataSource obtainSecurityMetadataSource() {return this.securityMetadataSource;}public void setSecurityMetadataSource(FilterInvocationSecurityMetadataSource newSource) {this.securityMetadataSource = newSource;}@Overridepublic void destroy() {}@Overridepublic void init(FilterConfig arg0) throws ServletException {}}



MyUserDetailService.java
package com.security;import java.util.ArrayList;import java.util.Collection;import java.util.Iterator;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.dao.DataAccessException;import org.springframework.security.core.GrantedAuthority;import org.springframework.security.core.authority.GrantedAuthorityImpl;import org.springframework.security.core.userdetails.User;import org.springframework.security.core.userdetails.UserDetails;import org.springframework.security.core.userdetails.UserDetailsService;import org.springframework.security.core.userdetails.UsernameNotFoundException;import com.pojo.Roles;import com.pojo.Users;import com.pojo.UsersRoles;import com.service.IRolesService;import com.service.IUsersService;// <!-- 认证管理器,实现用户认证的入口,主要实现UserDetailsService接口即可 -->public class MyUserDetailService implements UserDetailsService {@Autowiredpublic IUsersService usersService;@Autowiredpublic IRolesService rolesService;@Overridepublic UserDetails loadUserByUsername(String username)throws UsernameNotFoundException, DataAccessException {Collection<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();String password = null;System.out.println("-----> 载入用户的信息:loadUserByUsername()");/*if (username.equals("admin")) {password="admin";GrantedAuthorityImpl auth1 = new GrantedAuthorityImpl("ROLE_ADMIN");auths.add(auth1);System.out.println("-----> 设定用户角色[ROLE_ADMIN]:loadUserByUsername()");}*///获得登陆用户信息Users loginUser = usersService.getUserByUserName(username);if(loginUser!=null){password=loginUser.getPassword();if(loginUser.getUsersRoleses()!=null){//设定用户权限Iterator it = loginUser.getUsersRoleses().iterator();while(it.hasNext()){UsersRoles ur = (UsersRoles)it.next();Roles role = rolesService.getRolesById(ur.getId().getRoleId());GrantedAuthorityImpl auth1 = new GrantedAuthorityImpl(role.getName());auths.add(auth1);System.out.println("-----> 设定用户["+loginUser.getName()+"]角色["+role.getName()+"]:loadUserByUsername()");}}}// User(String username, String password, boolean enabled, boolean// accountNonExpired,// boolean credentialsNonExpired, boolean accountNonLocked,// Collection<GrantedAuthority> authorities) {User user = new User(username, password, true, true, true, true, auths);return user;}}



9.Security配置文件:applicationContext-security.xml
<?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.0.xsd">        <!-- 这里启动Service层方法保护 -->    <global-method-security secured-annotations="enabled" jsr250-annotations="enabled" pre-post-annotations="enabled"/>         <http access-denied-page="/common/403.jsp"><!-- 当访问被拒绝时,会转到403.jsp -->          <intercept-url pattern="/login.jsp" filters="none" />          <form-login login-page="/login.jsp"               authentication-failure-url="/login.jsp?error=true"               default-target-url="/index.jsp" />          <logout logout-success-url="/login.jsp" />          <http-basic />          <!-- 增加一个filter,这点与Acegi是不一样的,不能修改默认的filter了,这个filter位于FILTER_SECURITY_INTERCEPTOR之前 -->          <custom-filter before="FILTER_SECURITY_INTERCEPTOR" ref="myFilter" />      </http>        <!-- 一个自定义的filter,必须包含authenticationManager,accessDecisionManager,securityMetadataSource三个属性,       我们的所有控制将在这三个类中实现,解释详见具体配置 -->      <beans:bean id="myFilter" ref="authenticationManager" />          <beans:property name="accessDecisionManager" ref="myAccessDecisionManagerBean" />          <beans:property name="securityMetadataSource" ref="securityMetadataSource" />      </beans:bean>            <!-- 认证管理器,实现用户认证的入口,主要实现UserDetailsService接口即可 -->      <authentication-manager alias="authenticationManager">          <authentication-provider              user-service-ref="myUserDetailService">              <!--    如果用户的密码采用加密的话,可以加点“盐”                   <password-encoder hash="md5" />              -->          </authentication-provider>      </authentication-manager>      <beans:bean id="myUserDetailService" />        <!-- 访问决策器,决定某个用户具有的角色,是否有足够的权限去访问某个资源 -->      <beans:bean id="myAccessDecisionManagerBean" /> </beans:beans> 



10.View文件,只给出login和index的jsp,和403.jsp,其他见附件
login.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>  <head>    <base href="<%=basePath%>">    <title>Login Page</title>  </head>    <body>    <form name="f" action="j_spring_security_check" method="post">    UserName:<input type="text" id="j_username" name="j_username" value="admin">    <br>    Password:<input type="password" id="j_password" name="j_password" value="admin">    <br>    <input type="submit" value="Submit">    </form>  </body></html>



index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="ISO-8859-1"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>  <head>    <base href="<%=basePath%>">    <title>Index</title>  </head>    <body>  No Auth:<a href="./saveAndSearch.do">save And search</a>  <br>  <a href="./search1.do">@Secured Auth</a>  <a href="./search2.do">@RolesAllowed Auth</a>  <a href="./search3.do">@PreAuthorized Auth</a>  <a href="./search4.do">@PostAuthorized Auth</a>    <br>  Admin Group:<a href="./pages/admin/index1_1.jsp">Admin 1</a>  <a href="./pages/admin/index1_2.jsp">Admin 2</a>  <a href="./pages/admin/index1_3.jsp">Admin 3</a>  <a href="./pages/admin/index1_4.jsp">Admin 4</a>  <a href="./pages/admin/index1_5.jsp">Admin 5</a>    <br>  User Group:<a href="./pages/user/index1_1.jsp">User 1</a>  <a href="./pages/user/index1_2.jsp">User 2</a>  <a href="./pages/user/index1_3.jsp">User 3</a>  <a href="./pages/user/index1_4.jsp">User 4</a>  <a href="./pages/user/index1_5.jsp">User 5</a>  </body></html>
1 楼 JOHN_226 2012-04-12   高手在民间

热点排行