`
hanqunfeng
  • 浏览: 1526822 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

SpringSecurity3.X--一个简单实现

阅读更多

目录

SpringSecurity3.X--一个简单实现

SpringSecurity3.X--前台与后台登录认证

SpringSecurity3.X--remember-me

SpringSecurity3.X--验证码

 

作者对springsecurity研究不深,算是个初学者吧,最近很不完整的看了一下翻译的很是生硬的《Spring3Security-3.0.1中文官方文档.pdf》,为了便于学习和记忆,所以将所学知识在此记录下来。

这里给出一个简单的安全验证的实现例子,先说一下需求:

1.通过登录页面进行登录

2.用户登录前访问被保护的地址时自动跳转到登录页面

3.用户信息存储在数据表中

4.用户权限信息存在在数据表中

5.用户登录成功后访问没有权限访问的地址时跳转到登录页面

 

ok,以上就是一个基本的需求了,大部分的系统都是基于该需求实现登录模块的。

 

给出实现之前,先简单说明一下springsecurity的原理,

1.AccessDecisionManager

和我们一般实现登录验证采用filter的方式一样,springsecurity也是一个过滤器,当请求被springsecurity拦截后,会先对用户请求的资源进行安全认证,如果用户有权访问该资源,则放行,否则将阻断用户请求或提供用户登录,

在springsecurity中,负责对用户的请求资源进行安全认证的是AccessDecisionManager,它就是一组投票器的集合,默认的策略是使用一个AffirmativeBased,既只要有一个投票器通过验证就允许用户访问,

所以如果希望实现自己的权限验证策略,实现自己的投票器是一个很好的选择。

 

2.UserDetailsService

如果用户没有登录就访问某一个受保护的资源,则springsecurity会提示用户登录,用户登录后,由UserDetailsService来验证用户是否合法,既验证用户名和密码是否正确,同时验证用户是否具备相应的资源权限,

即对应的access的value。

如果用户验证通过,则由AccessDecisionManager来决定是否用户可以访问该资源。

 

下面给出具体实现:

web.xml

基本上都是这样配置,就不废话了。

<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>
 

applicationContext-security.xml

 

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:util="http://www.springframework.org/schema/util" xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:tool="http://www.springframework.org/schema/tool" xmlns:beans="http://www.springframework.org/schema/beans"
	xsi:schemaLocation="
			http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
			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/jee http://www.springframework.org/schema/jee/spring-jee-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/util http://www.springframework.org/schema/util/spring-util-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/tool http://www.springframework.org/schema/tool/spring-tool-3.0.xsd
			http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd"
	default-lazy-init="true">

        <!-- 不需要进行认证的资源,3.0之后才改为这样配置 -->
	<http security="none" pattern="/index.do" />

        <!-- 因为要使用自己的权限验证规则,所以这里要配置access-decision-manager-ref
         实际上,我只是在accessDecisionManager中增加了一个投票器,其它的属性都比较简单,不多说了 -->
	<http auto-config='true' access-decision-manager-ref="accessDecisionManager"
		access-denied-page="/index.do">
		<intercept-url pattern="/demo.do*" access="IS_AUTHENTICATED_REMEMBERED" />
		<intercept-url pattern="/**/*.do*" access="HODLE" />
		<logout logout-url="/logout.do" invalidate-session="true"
			logout-success-url="/logout.jsp" />
		<form-login login-page="/index.do" default-target-url="/frame.do"
			always-use-default-target="true" authentication-failure-url="/index.do?login_error=1" />
		<session-management>
			<concurrency-control max-sessions="1" />
		</session-management>
	</http>



	<!-- Automatically receives AuthenticationEvent messages -->
	<beans:bean id="loggerListener"
		class="org.springframework.security.authentication.event.LoggerListener" />

       <!-- 认证管理器,使用自定义的UserDetailsService,并对密码采用md5加密-->
	<authentication-manager>
		<authentication-provider user-service-ref="userService">
			<password-encoder hash="md5" />
		</authentication-provider>
	</authentication-manager>

	<beans:bean id="userService" class="com.piaoyi.common.security.UserService" />

         <!-- 访问决策管理器,这里使用AffirmativeBased,并加入一个自定义的投票器DynamicRoleVoter -->
	<beans:bean id="accessDecisionManager"
		class="org.springframework.security.access.vote.AffirmativeBased">
		<beans:property name="decisionVoters">
			<beans:list>
				<beans:bean class="org.springframework.security.access.vote.RoleVoter" />
				<beans:bean
					class="org.springframework.security.access.vote.AuthenticatedVoter" />
				<beans:bean class="com.piaoyi.common.security.DynamicRoleVoter" />
			</beans:list>
		</beans:property>
	</beans:bean>
</beans:beans>
 

UserService.java

 

public class UserService implements UserDetailsService{

	@Autowired
	private ISystemUserService userService;
	@Override
	public UserDetails loadUserByUsername(String username)
			throws UsernameNotFoundException {
		// TODO Auto-generated method stub
		SystemUser user = userService.findById(username);		
		if (user == null)
			throw new UsernameNotFoundException("The user name " + username
					+ " can not be found!");

		List<GrantedAuthority> resultAuths = new ArrayList<SystemAuthority>();
               //增加access中配置的权限,实际上这里就是让所有登陆用户都具备该权限,
               //而真正的资源权限验证留给AccessDecisionManager来决定
                resultAuths.add(new GrantedAuthorityImpl("HODLE"));
		
		//验证用户名和密码是否正确,以及是否权限正确
		return new User(username, user.getPassword().toLowerCase(), user.isStatus(), true,
				true, true, resultAuths);
		
		
	}
}
 

DynamicRoleVoter.java

public class DynamicRoleVoter  implements
		AccessDecisionVoter {

	@Autowired
	private ISystemUserService userService;

	private PathMatcher pathMatcher = new AntPathMatcher();
	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.springframework.security.vote.AccessDecisionVoter#supports(java.lang
	 * .Class)
	 */
	@SuppressWarnings("unchecked")
	public boolean supports(Class clazz) {
		return true;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @seeorg.springframework.security.vote.AccessDecisionVoter#supports(org.
	 * springframework.security.ConfigAttribute)
	 */
	public boolean supports(ConfigAttribute attribute) {
		return true;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @seeorg.springframework.security.vote.AccessDecisionVoter#vote(org.
	 * springframework.security.Authentication, java.lang.Object,
	 * org.springframework.security.ConfigAttributeDefinition)
	 */
	public int vote(Authentication authentication, Object object,
			java.util.Collection arg2) {
		int result = ACCESS_ABSTAIN;
		if (!(object instanceof FilterInvocation))
			return result;
		FilterInvocation invo = (FilterInvocation) object;
		String url = invo.getRequestUrl();//当前请求的URL
		Set<GrantedAuthority> authorities = null;
		String userId = authentication.getName();
		//获得当前用户的可访问资源,自定义的查询方法,之后和当前请求资源进行匹配,成功则放行,否则拦截	
		authorities = loadUserAuthorities(userService.findById(userId));
		Map<String, Set<String>> urlAuths = authService.getUrlAuthorities();
		Set<String> keySet = urlAuths.keySet();
		for (String key : keySet) {
			boolean matched = pathMatcher.match(key, url);
			if (!matched)
				continue;
			Set<String> mappedAuths = urlAuths.get(key);
			if (contain(authorities, mappedAuths)) {
				result = ACCESS_GRANTED;
				break;
			}
		}
		return result;
	}
	
	
	protected boolean contain(Set<GrantedAuthority> authorities,
			Set<String> mappedAuths) {
		if (CollectionUtils.isEmpty(mappedAuths)
				|| CollectionUtils.isEmpty(authorities))
			return false;
		for (GrantedAuthority item : authorities) {
			if (mappedAuths.contains(item.getAuthority()))
				return true;
		}
		return false;
	}
}
 

 

OK。

 

分享到:
评论
3 楼 执衣卖水 2012-01-16  
如果方便,可以发份代码吗?
daim6n@gmail.com
2 楼 hanqunfeng 2011-09-30  
calvinlq 写道
authorities = loadUserAuthorities(userService.findById(userId)); 
        Map<String, Set<String>> urlAuths = authService.getUrlAuthorities(); 

loadUserAuthorities

authService

这两个哪里来的?

代码没有给完整,实际是自己定义的方法,如下
        @Autowired
protected ISystemAuthorityService authService;

@Autowired
protected ISystemUserService userService;
        /**
* 根据用户获取其相应的权限列表
*
* @param user
*            用户信息
* @return 权限列表
*/
protected Set<GrantedAuthority> loadUserAuthorities(SystemUser user) {
Set<SystemAuthority> sysauths = user.getAuthorities();
if (sysauths == null)
return null;
Set<GrantedAuthority> results = new HashSet<GrantedAuthority>();
for (Iterator<SystemAuthority> it = sysauths.iterator(); it.hasNext();) {
results.add(new GrantedAuthorityImpl(authService
.getAuthorityPrefix()
+ it.next().getId()));
}
return results;
}
1 楼 calvinlq 2011-09-30  
authorities = loadUserAuthorities(userService.findById(userId)); 
        Map<String, Set<String>> urlAuths = authService.getUrlAuthorities(); 

loadUserAuthorities

authService

这两个哪里来的?

相关推荐

    SpringSecurity 3.0.1.RELEASE.CHM

    A.3. ACL表 A.3.1. Hypersonic SQL A.3.1.1. PostgreSQL B. 安全命名空间 B.1. Web应用安全 - 元素 B.1.1. 属性 B.1.1.1. servlet-api-provision B.1.1.2. path-type B.1.1.3. lowercase-comparisons B....

    Spring Security 中文教程.pdf

    19.3.3. 读取授权 19.4. 实现类 19.4.1. LdapAuthenticator实现 19.4.1.1. 常用功能 19.4.1.2. BindAuthenticator 19.4.1.3. PasswordComparisonAuthenticator 19.4.1.4. 活动目录认证 19.4.2. 链接到...

    Spring Security-3.0.1中文官方文档(翻译版)

    这次发布的Spring Security-3.0.1 是一个bug fix 版,主要是对3.0 中存在的一些问题进 行修 正。文档中没有添加新功能的介绍,但是将之前拼写错误的一些类名进行了修正,建议开发 者以这一版本的文档为参考。 ...

    spring security 5.x实现兼容多种密码的加密方式

    spring security针对该功能有两种实现方式,一种是简单的使用加密来保证基于 cookie 的 token 的安全,另一种是通过数据库或其它持久化存储机制来保存生成的 token。这篇文章主要给大家介绍了关于spring security 5....

    spring security 的一些资料----下载不扣分,回帖加1分,童叟无欺,欢迎下载

    Spring Security中可以使用Acegi-1.x时代的普通配置方式,也可以使用从2.0时代才出现的命名空间配置方式,实际上这两者实现的功能是完全一致的,只是新的命名空间配置方式可以把原来需要几百行的配置压缩成短短的几...

    spring security 参考手册中文版

    设置一个自定义的AuthenticationEntryPoint 64 6.4方法安全 64 6.4.1 &lt;global-method-security&gt;元素 65 使用protect-pointcut添加安全性切入点 66 6.5默认AccessDecisionManager 67 6.5.1自定义...

    springboot-springsecurity-jwt-demo

    内容是一个正确的JWT格式 检查签名 检查claims 检查权限 处理登录 创建一个类JWTLoginFilter,核心功能是在验证用户名密码正确后,生成一个token,并将token返回给客户端: 该类继承自...

    spring boot 全面的样例代码

    - chapter1:[基本项目构建(可作为工程脚手架),引入web模块,完成一个简单的RESTful API](http://blog.didispace.com/spring-boot-learning-1/) - [使用Intellij中的Spring Initializr来快速构建Spring Boot/...

    Simple-Social-Login-System:一个基于springSecurity和springBoot的qq等第三方软件登录系统

    一个基于springSecurity+springBoot的社交化登录系统 1. 技术选型 springBoot:使用spring框架简单方便 springSecurity:与spring框架无缝连接 mysql:免费,方便 redis:强大,使用广泛的缓存 freemarker:...

    springboot学习

    chapter1:基本项目构建(可作为工程脚手架),引入web模块,完成一个简单的RESTful API 使用Intellij中的Spring Initializr来快速构建Spring Boot/Cloud工程 工程配置 chapter2-1-1:配置文件详解:自定义属性、...

    renren-security是一个轻量级权限管理系统

    一个轻量级权限管理系统,其核心设计目标是开发迅速、学习简单、轻量级、易扩展;使用Spring MVC、Shiro、MyBatis、Bootstrap、Vue2.x等框架,包含:管理员管理、角色管理、菜单管理、定时任务、参数管理、代码生成...

    Spring攻略(第二版 中文高清版).part1

    14.1 用Spring Portlet MVC开发一个简单的Portlet 544 14.1.1 问题 544 14.1.2 解决方案 545 14.1.3 工作原理 546 14.2 将Portlet请求映射到处理程序 553 14.2.1 问题 553 14.2.2 解决方案 553 14.2.3...

    Spring攻略(第二版 中文高清版).part2

    14.1 用Spring Portlet MVC开发一个简单的Portlet 544 14.1.1 问题 544 14.1.2 解决方案 545 14.1.3 工作原理 546 14.2 将Portlet请求映射到处理程序 553 14.2.1 问题 553 14.2.2 解决方案 553 14.2.3...

    JAVA上百实例源码以及开源项目源代码

    简单聊天软件CS模式 2个目标文件 一个简单的CS模式的聊天软件,用socket实现,比较简单。 凯撒加密解密程序 1个目标文件 1、程序结构化,用函数分别实现 2、对文件的加密,解密输出到文件 利用随机函数抽取幸运数字 ...

    JAVA上百实例源码以及开源项目

    一个简单的CS模式的聊天软件,用socket实现,比较简单。 凯撒加密解密程序 1个目标文件 1、程序结构化,用函数分别实现 2、对文件的加密,解密输出到文件 利用随机函数抽取幸运数字 简单 EJB的真实世界模型(源代码...

    DWR.xml配置文件说明书(含源码)

    spring Location* 任何以location开头的参数,每个参数都是指定一个spring的配置文件,在参数没有设置的情况下DWR会去读取spring的全局的配置文件. spring beanName 从配置文件中读取的bean的名称 “scope参数允许你...

    基于springboot的设备管理系统+源代码+文档说明

    **项目说明** - 采用SpringBoot、MyBatis...3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

    xmljava系统源码-renren-msg:基于renren开源的短信平台

    renren-security是一个轻量级权限管理系统,其核心设计目标是开发Swift、学习简单、轻量级、易扩展 使用renren-security搭建项目,只需编写30%左右代码,其余的代码交给系统自动生成 一个月的工作量,一周就能完成,...

    renren-security:采用Spring,MyBatis,Shiro框架,开发的一套权限系统,极低门云,拿来即用

    通过注解实现数据权限的控制完善的XSS预防及脚本过滤,彻底杜绝XSS攻击支持分布式部署,session存储在redis中友好的代码结构及注释,便于阅读及二次开发♡quartz定时任务,可动态完成任务的添加,修改,删除,暂停,...

Global site tag (gtag.js) - Google Analytics