`
andy_ghg
  • 浏览: 293782 次
  • 性别: Icon_minigender_1
  • 来自: 扬州
社区版块
存档分类
最新评论

MyEclipse中Spring Security 3.0.3无废话配置(第二章)。

    博客分类:
  • Java
阅读更多
上回说到数据库验证首先看以往的验证配置:
<authentication-manager>  
    <authentication-provider>  
        <user-service>  
            <user name="jimi" password="jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />  
            <user name="bob" password="bobspassword" authorities="ROLE_USER" />  
        </user-service>  
    </authentication-provider>  
</authentication-manager>  

现在我们要用数据库来验证。
第一步:建立数据库
这里只用两张表即可解决问题,也许你看过很多建立五张到七张的,那是实际在项目中才这样做,我们做试验的话在这里只建立两张表:1.用户表2.资源表。
用户表四个字段:ID、USERNAME、PASSWORD、ROLE(权限)
资源表有三个字段:ID、资源路径、访问权限
资源路径就是一个URL地址,访问权限就是这个资源需要什么样子的权限才能访问。


第二步:权限提供
package cn.com.fri.security.supports;

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 javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
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 org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.com.fri.security.dao.interfaces.IAuthoritiesDAO;
import cn.com.fri.security.dao.interfaces.IResourcesDAO;
import cn.com.fri.security.vo.Authorities;
import cn.com.fri.security.vo.Resources;

/**
 * 
 * 此类在初始化时,应该取到所有资源及其对应角色的定义
 * 
 */
@Service("securityMetadataSource")
public class MyInvocationSecurityMetadataSource implements
		FilterInvocationSecurityMetadataSource {
	@Autowired
	private IAuthoritiesDAO authoritiesDAO;
	@Autowired
	private IResourcesDAO resourcesDAO;

	private UrlMatcher urlMatcher = new AntUrlPathMatcher();;
	private static Map<String, Collection<ConfigAttribute>> resourceMap = null;

	public MyInvocationSecurityMetadataSource() {
	}

	/**
	 * 在此处,将数据库中所有的资源以及对应的权限加入到内存中
	 */
	@PostConstruct
	public void loadResourceDefine() {
		resourceMap = new HashMap<String, Collection<ConfigAttribute>>();
		Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();
		System.out.println(authoritiesDAO);
		List<Authorities> auth = authoritiesDAO.findAll();
		for (Authorities au : auth) {
			ConfigAttribute ca = new SecurityConfig(au.getAuthorname());
			atts.add(ca);
		}
		List<Resources> res = resourcesDAO.findAll();
		for (Resources resources : res) {
			resourceMap.put(resources.getResourcesstring(), atts);
		}
		System.out.println("权限加载完毕");
	}

	// According to a URL, Find out permission configuration of this URL.
	@Transactional(readOnly = true)
	public Collection<ConfigAttribute> getAttributes(Object object)
			throws IllegalArgumentException {
		// 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;
	}

	public void setAuthoritiesDAO(IAuthoritiesDAO authoritiesDAO) {
		this.authoritiesDAO = authoritiesDAO;
	}

	public void setResourcesDAO(IResourcesDAO resourcesDAO) {
		this.resourcesDAO = resourcesDAO;
	}

}

找个类的作用就是在服务器启动的时候将存放在数据库表中的资源与访问权限加载到内存中去。

第三步:编写路径验证类:
package cn.com.fri.security.supports;

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;
import org.springframework.stereotype.Service;
@Service("myAccessDecisionManagerBean")
public class MyAccessDecisionManager implements AccessDecisionManager {

	public void decide(Authentication authentication, Object object,
			Collection<ConfigAttribute> configAttributes)
			throws AccessDeniedException, InsufficientAuthenticationException {
		if (configAttributes == null) {
			return;
		}
		
		Iterator<ConfigAttribute> ite = configAttributes.iterator();
		while (ite.hasNext()) {
			ConfigAttribute ca = ite.next();
			String needRole = ((SecurityConfig) ca).getAttribute();
			for (GrantedAuthority ga : authentication.getAuthorities()) {
				if (needRole.equals(ga.getAuthority())) { // ga is user's role.
					return;
				}
			}
		}
		throw new AccessDeniedException("no right");
	}

	public boolean supports(ConfigAttribute attribute) {
		// TODO Auto-generated method stub
		return true;
	}

	public boolean supports(Class<?> clazz) {
		return true;
	}

}

此类用户判断当前登录的用户是否有权限访问某个路径。而这里路径的访问权限就是从内存中取出来的。
第四步:登录验证:
package cn.com.fri.security.supports;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

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.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.com.fri.security.dao.interfaces.IUsersDAO;
import cn.com.fri.security.vo.Authorities;
import cn.com.fri.security.vo.CustomUser;
import cn.com.fri.security.vo.Users;

@Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {

	@Autowired
	private IUsersDAO dao;

	@Transactional(readOnly = true)
	public UserDetails loadUserByUsername(String username)
			throws UsernameNotFoundException, DataAccessException {
		System.out.println(username);
		Users user = dao.findByUsername(username).get(0);//此查询由自己去实现
		if (user == null)
			throw new UsernameNotFoundException("user not found");
		Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();

		List<Authorities> auths = dao.findAutByUsername(username);//此查询由自己去实现如果用户表中已经包含了权限,就无需进行这一步操作了。
		System.out.println(">>>>>>获得的权限有:" + auths.size() + "个");
		for (Authorities a : auths) {
			GrantedAuthorityImpl authorityImpl = new GrantedAuthorityImpl(a
					.getAuthorname());
			authorities.add(authorityImpl);
		}
		CustomUser u = new CustomUser(username, user.getPsw(), user
				.getEnabled(), true, true, true, authorities);
		u.setUser(user);
		return u;
	}
}

在这个类中,用户一旦登录,我们就能获取到用户的权限,将用户权限放入到CustomUser中,然后返回这个CustomUser即可。CustomUser为继承自org.springframework.security.core.userdetails.User的一个类,继承的原因是为了让原来的User能够拥有更多的属性,例如用户的中文名称等等。里面的List<Authorities> auths = dao.findAutByUsername(username);这一步是因为我是按照七张表的结构去建立的,因此如果你只有两张表,这里完全可以省略。你甚至可以在这里写死(试验用)如下:
GrantedAuthorityImpl authorityImpl = new GrantedAuthorityImpl("ROLE_ADMIN");
authorities.add(authorityImpl);

第五步:配置SS3的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">
	<http auto-config='true' access-denied-page="/common/403.jsp">
		<!-- 以下为不需要权限就能访问的资源**意思就是包括子目录也同样适用 -->
		<intercept-url pattern="/css/**" filters="none" />
		<intercept-url pattern="/app/**" filters="none" />
		<intercept-url pattern="/images/**" filters="none" />
		<intercept-url pattern="/swf/**" filters="none" />
		<intercept-url pattern="/login.jsp*" access="IS_AUTHENTICATED_ANONYMOUSLY" />
		<form-login login-page='/login.jsp' default-target-url="/index.do"
			always-use-default-target="true" />
		<!-- 配置退出登录 -->
		<logout invalidate-session="true" logout-url="/logout"
			logout-success-url="/login.jsp" />
		<session-management invalid-session-url="/error.html">
			<concurrency-control max-sessions="1"
				expired-url="/error.html" />
		</session-management>
		<!--
			配置登录验证,包括权限的启动都在这里:
		-->
		<custom-filter before="FILTER_SECURITY_INTERCEPTOR" ref="myFilter" />
	</http>
	
	<!-- 配置登录验证的类 -->
	<beans:bean id="daoAuthenticationProvider"
		class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
		<beans:property name="userDetailsService" ref="userDetailsService" />
	</beans:bean>

	<beans:bean id="authenticationManager"
		class="org.springframework.security.authentication.ProviderManager">
		<beans:property name="providers">
			<beans:list>
				<beans:ref local="daoAuthenticationProvider" />
			</beans:list>
		</beans:property>
	</beans:bean>
	
	<authentication-manager>
		<authentication-provider user-service-ref="userDetailsService">
		</authentication-provider>
	</authentication-manager>


	<!--
		一个自定义的filter,必须包含authenticationManager,accessDecisionManager,securityMetadataSource三个属性,
		我们的所有控制将在这三个类中实现,这里使用了annocation,所以ref后面的参数在XML配置中是没有的,详细看这三个类。
	-->
	<beans:bean id="myFilter"
		class="cn.com.fri.security.supports.MyFilterSecurityInterceptor">
		<beans:property name="authenticationManager" ref="authenticationManager" />
		<beans:property name="accessDecisionManager" ref="myAccessDecisionManagerBean" />
		<beans:property name="securityMetadataSource" ref="securityMetadataSource" />
	</beans:bean>

</beans:beans>


由于东西较多,所以再一开始的时候建议大家去下载官方的说明文档和中文翻译的说明文档。
在此我们的配置结束。这一部分虽然代码比较多,但是其实一点不复杂,仔仔细细的看一遍就会了。
分享到:
评论
6 楼 516816168 2011-08-19  
详细,不错啊
5 楼 mfx258 2011-06-13  
andy_ghg 写道
就是登录后根本没有进入到UserDetailsServiceImpl这个类是吗?

进入这个类了,下面是后台日志输出:
INFO : com.sywzsh.security.PawnUsersDetailsService - auths===[AUTH_AFTERLOGINWELCOME, AUTH_LOGIN, AUTH_NODE_MGR, AUTH_XTSZ_DEPT, AUTH_XTSZ_USER, AUTH_AFTERLOGINWELCOME, AUTH_LOGIN, AUTH_AFTERLOGINWELCOME, AUTH_XTSZ_DEPT, AUTH_XTSZ_USER, AUTH_NODE_MGR]
INFO : com.sywzsh.security.dao.SysUsersDao - 根据UserAccount查找SysUsers实例对象: admin

INFO : com.sywzsh.security.dao.SysUsersDao - 相匹配的SysUsers实例对象被找到!

问题是在这一步
public Collection<ConfigAttribute> getAttributes(Object object)  
            throws IllegalArgumentException {  
        // guess object is a URL.  
        String url = ((FilterInvocation) object).getRequestUrl();  
        log.info("url====="+url);
        Iterator<String> ite = resourceMap.keySet().iterator();  
        while (ite.hasNext()) {  
            String resURL = ite.next();  
            if (urlMatcher.pathMatchesUrl(url, resURL)) {  
                return resourceMap.get(resURL);  
            }  
        }  
        return null;  
    }  


其中:log.info("url====="+url);打印出的是/jsp/fail.jsp,这个链接是在security.xml中配置的认证失败跳转页面
<form-login login-page="/jsp/admin/login.jsp" login-processing-url="/topic/add"
			authentication-failure-url="/jsp/fail.jsp" default-target-url="/jsp/index.jsp" />

点登录按钮,应该判断/jsp/index.jsp是否有权限,不知道为什么直接就跳到失败页面了
4 楼 andy_ghg 2011-06-13  
就是登录后根本没有进入到UserDetailsServiceImpl这个类是吗?
首先看一下是否进入了这个类,并且成功调用了loadUserByUsername这个方法(此方法是UserDetailsService接口提供的)。

按理来说,点击登录之后是应该调用这个方法的。如果没有调用,你查看一下这里的配置是否正确:
	<!-- 配置登录验证的类 -->
	<beans:bean id="daoAuthenticationProvider"
		class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<!--------注意这里------------>
		<beans:property name="userDetailsService" ref="userDetailsService" />
	</beans:bean>

	<beans:bean id="authenticationManager"
		class="org.springframework.security.authentication.ProviderManager">
		<beans:property name="providers">
			<beans:list>
				<beans:ref local="daoAuthenticationProvider" />
			</beans:list>
		</beans:property>
	</beans:bean>
	
	<authentication-manager>
<!--------注意这里------------>
		<authentication-provider user-service-ref="userDetailsService">
		</authentication-provider>
	</authentication-manager>

里面的ref是参考了UserDetailServiceImple的annocation:
@Service("userDetailsService")  
public class UserDetailsServiceImpl implements UserDetailsService {  
    //..............
}
3 楼 mfx258 2011-06-13  
我扩展了userDetails 代码如下
List<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();
		
		//得到用户的权限
		auths = sysUsersDao.loadUserAuthoritiesByUserName( username );
		
		log.info("auths==="+auths);
		
		//根据用户名取得一个SysUsers对象,以获取该用户的其他信息。
		SysUsersBean user = sysUsersDao.findByUserName( username );
		log.info("user===="+user);
		return new SysUsers( user.getUserId(), user.getUserAccount(), user.getUserName(),
				 user.getUserPassword(),user.getUserDesc(), user.getEnabled(), user.getIssys(),
				 user.getUserDuty(), user.getUserDept(), 
				 new HashSet(0), true, true, true, auths);


如果未登录,直接跳到登陆页面,比如访问/jsp/admin/security/role.jsp,后台输出

INFO : com.sywzsh.security.PawnInvocationSecurityMetadataSourceService - getAttributes(Object)=========/jsp/admin/security/role.jsp
INFO : com.sywzsh.security.PawnAccessDecisionManagerService - decide(Authentication, Object, Collection<ConfigAttribute>) - start
INFO : com.sywzsh.security.PawnAccessDecisionManagerService - 正在访问的url是:FilterInvocation: URL: /jsp/admin/security/role.jsp
INFO : com.sywzsh.security.PawnAccessDecisionManagerService - needRole is:AUTH_XTSZ_USER
INFO : com.sywzsh.security.PawnAccessDecisionManagerService - 授权信息是:ROLE_ANONYMOUS

这个是正确的,但输入用户名和密码后,再点登录,默认应该跳到
default-target-url="/index.jsp"

但后台什么输出都没有,直接又回到登录页面了
2 楼 andy_ghg 2011-06-13  
mfx258 写道
您好,按照您的配置,启动没有问题,只是在登录时,点击登录后直接跳到验证失败页面,debug跟踪发现,InvocationSecurityMetadataSourceService中的getAttributes(Object object)方法传入的object值就是验证失败页面的url,还有什么地方需要配置吗?

你好,首先看一下UserDetailsServiceImpl这个类中的
   CustomUser u = new CustomUser(username, user.getPsw(), user  
                .getEnabled(), true, true, true, authorities);  

有没有执行到这里。并且里面的authorities是否包含了权限,既:
GrantedAuthorityImpl authorityImpl = new GrantedAuthorityImpl("ROLE_ADMIN");  
authorities.add(authorityImpl);  

有没有类似的代码?

如果有的话,你的数据库中的资源所需权限是否与之相等,例如:
URL                   ROLE
/index.jsp         ROLE_ADMIN


1 楼 mfx258 2011-06-12  
您好,按照您的配置,启动没有问题,只是在登录时,点击登录后直接跳到验证失败页面,debug跟踪发现,InvocationSecurityMetadataSourceService中的getAttributes(Object object)方法传入的object值就是验证失败页面的url,还有什么地方需要配置吗?

相关推荐

    myeclipse 8.5的spring security 2.0.5的简单练习(图解)

    ### MyEclipse 8.5 中 Spring Security 2.0.5 的简易实践 #### 一、背景介绍 本篇文章将详细介绍如何在 MyEclipse 8.5 中使用 Spring Security 2.0.5 来实现一个简单的权限管理示例。Spring Security 是一个功能...

    Spring在MyEclipse中的配置

    ### Spring在MyEclipse中的配置详解 #### 一、引言 随着企业级应用的不断发展,Spring框架因其轻量级且强大的依赖注入(Dependency Injection, DI)与面向切面编程(Aspect-Oriented Programming, AOP)能力而受到...

    myeclipse中spring配置文件输入提示配置.docx

    ### MyEclipse中Spring配置文件输入提示配置详解 #### 一、问题背景及解决思路概述 在使用MyEclipse进行Java开发时,特别是在涉及到Spring框架的应用中,经常会遇到配置文件编辑过程中缺乏智能提示的问题。这对于...

    使用MyEclipse查看Spring的依赖视图

    #### 二、MyEclipse中添加对Spring的支持 为了能够利用MyEclipse查看Spring的依赖视图,首先需要确保MyEclipse支持Spring框架。以下是具体步骤: 1. **右键项目-&gt;MyEclipse-&gt;Add Spring Capabilities** - 打开你...

    在myeclipse自动提示spring的配置信息

    本篇将详细讲解如何在MyEclipse中设置和利用自动提示来获取Spring配置信息。 1. **安装Spring插件** 在MyEclipse中使用Spring的自动提示功能首先需要安装Spring IDE插件。可以通过MyEclipse的Marketplace或者下载...

    spring security3.2下载、配置

    security3.2最新版本配置,资源里面有4个小项目,都是利用maven搭建的,先在mysql中新建一个security空数据库,不要建表,然后只要在myeclipse导入,运行maven install,在连网状态下就会自动下载jar包了,无需再去...

    myeclipse for spring 8.6

    根据提供的文件信息,“myeclipse for spring 8.6”主要涉及的是MyEclipse这款集成开发环境(IDE)与Spring框架结合使用的版本介绍及相关知识点。接下来将从几个方面详细阐述这些知识点。 ### 一、MyEclipse简介 ...

    解决Myeclipse中spring配置文件无提示.docx

    在使用MyEclipse进行Spring框架开发时,可能会遇到一个常见的问题,即在编辑Spring配置文件时没有代码提示。这个问题通常是由于MyEclipse无法访问到Spring的XML Schema定义文件导致的。Spring的XML Schema文件通常...

    MyEclipse for spring9.0下载地址

    1. **Spring框架集成**:MyEclipse for Spring 9.0提供了一整套针对Spring框架的支持工具,包括但不限于Spring项目创建、配置管理、代码自动生成等功能。 2. **增强的编辑器**:具备强大的代码编辑功能,支持语法...

    MyEclipse for Spring环境注册码

    在MyEclipse中集成Spring环境,意味着开发者可以利用MyEclipse的高级功能来优化Spring框架的应用。这包括但不限于代码自动生成、智能提示、调试工具以及对Spring配置文件的可视化编辑等功能。这些功能的集成,大大...

    MyEclipse For Spring 8.6.5

    MyEclipse For Spring 8.6.5

    MyEclipse Spring 快速入门中文教程

    本教程旨在帮助初学者快速掌握如何在MyEclipse中配置和使用Spring框架,从而提升开发效率。 **1. 安装与配置MyEclipse** 首先,你需要下载并安装MyEclipse。安装过程中,确保选择了包含Spring支持的选项。安装完成...

    用MyEclipse开发spring.doc

    通过以上步骤,你已经成功地在 MyEclipse 中搭建了 Spring 开发环境,并完成了一个简单的案例,展示了如何使用 Spring 进行依赖注入和接口实现。在实际项目中,你可以根据需求扩展 Bean 配置,以及利用 Spring 提供...

    基于myeclipse的spring学习的各种实例

    在本文中,我们将深入探讨如何基于MyEclipse和MySQL环境学习Spring框架,并通过一系列实例来掌握其核心概念和功能。Spring是一个开源的Java平台,它为构建企业级应用提供了全面的框架支持,包括依赖注入、面向切面...

    Spring Security学习总结一

    为了演示Spring Security的配置和使用,我们可以构建一个简单的Web项目,使用MyEclipse导入Spring和Spring Security的相关JAR包,然后配置Spring Security来保护Web资源。在本例中,用户信息(用户名、密码和权限)...

    MyEclipse For Spring 8.6.15

    MyEclipse For Spring 8.6.15

    spring security 3 登录 退出 认证 最少配置

    应用中涉及到安全认证,目前项目有独立的统一认证网关,所以登录时只需要将安全认证网关的认证后信息塞到spring security中,由security3来管理用户的权限设置。目前项目由spring security2升级到spring security3。...

    MyEclipse for spring8.6 注册机

    MyEclipse for spring8.6 注册机 有效期到2017年

    MyEclipse中配置JBoss

    【标题】:“MyEclipse中配置JBoss” 在IT行业中,MyEclipse是一款深受开发者喜爱的集成开发环境(IDE),尤其对于Java EE项目开发来说,它提供了强大的支持。而JBoss则是一个开源的应用服务器,广泛用于部署和管理...

    myeclipse for spring 10.1 crack

    myeclipse 10.1-10.5(myeclipse for spring 10.1)破解,已成功破解 1. 输入Usercode, 点击'SystemId...', 生成SystemId 2. 点击'Active', 生成LICENSE_KEY, ACTIVATION_CODE, ACTIVATION_KEY 3. 点击菜单'Tools -...

Global site tag (gtag.js) - Google Analytics