本文是一个简单的基于用户,角色,权限的spring security应用。
使用步骤:
1 在web.xml引入如下配置:
<listener> <listener-class> org.springframework.security.web.session.HttpSessionEventPublisher </listener-class> </listener>
2 增加spring security配置文件spring_security.xml(名称可以自己取):
<b:beans xmlns="http://www.springframework.org/schema/security" xmlns:b="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="false" access-denied-page="/accessDenied.jsp"> <!-- 不要过滤图片等静态资源,其中**代表可以跨越目录,*不可以跨越目录。 <intercept-url pattern="/**/*.jpg" filters="none" /> <intercept-url pattern="/**/*.png" filters="none" /> <intercept-url pattern="/**/*.gif" filters="none" /> <intercept-url pattern="/**/*.css" filters="none" /> <intercept-url pattern="/**/*.js" filters="none" /> --> <!-- 登录页面和忘记密码页面不过滤 --> <intercept-url pattern="/login.jsp" filters="none" /> <intercept-url pattern="/jsp/forgotpassword.jsp" filters="none" /> <!-- ROLE_ENTER_ORDINARY_PAGE, --> <intercept-url pattern="/index.jsp" access="ROLE_ENTER_ORDINARY_PAGE, ROLE_ENTER_HIGH_LEVEL_PAGE" /> <!-- 检测失效的sessionId,超时时定位到另外一个URL, 防止固化session攻击 --> <!-- <session-management invalid-session-url="/timeout.jsp" session-fixation-protection="migrateSession"> --> <session-management session-authentication-strategy-ref="sessionAuthenticationStrategy"> </session-management> <custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" /> <form-login login-page="/login.jsp" authentication-failure-url="/loginError.jsp" default-target-url="/index.jsp"/> <logout invalidate-session="true" logout-success-url="/login.jsp"/> <http-basic/> <!-- <remember-me user-service-ref="userService"/> --> <remember-me user-service-ref="userService" data-source-ref="myDataSource"/> <anonymous/> </http> <!-- 注意能够为authentication-manager 设置alias别名 --> <authentication-manager alias="authenticationManager"> <!-- <authentication-provider user-service-ref="userDetailsManager"> --> <authentication-provider user-service-ref="userService"> <password-encoder hash="md5"> <salt-source user-property="username"/> </password-encoder> <!-- <password-encoder ref="passwordEncoder"> --> <!-- 用户名做为盐值 --> <!--<salt-source user-property="username" /> </password-encoder>--> </authentication-provider> </authentication-manager> </b:beans>
3 在web.xml中添加spring security配置的引用
<context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/spring.xml, /WEB-INF/spring/spring_security.xml</param-value> </context-param>
4 创建用户,角色,权限表
--创建表t_user create table t_user( id int PRIMARY key auto_increment, username VARCHAR(50) not null, password varchar(50) not NULL ); --插入数据 insert into t_user values(null, 'user', '47a733d60998c719cf3526ae7d106d13'); insert into t_user values(null, 'admin', 'ceb4f32325eda6142bd65215f4c0f371'); --创建表t_Role create table ( id int PRIMARY key auto_increment, name VARCHAR(50) not null ); --插入数据 insert into t_role values(null, '普通用户'); insert into t_role values(null, '高级用户'); --创建表t_Perm create table t_perm( id int PRIMARY key auto_increment, name VARCHAR(50) not null ); --插入数据 insert into t_perm values(null, 'ROLE_ENTER_ORDINARY_PAGE'); insert into t_perm values(null, 'ROLE_ENTER_HIGH_LEVEL_PAGE'); --创建表角色--人员的关联关系(多对多) create table t_user_role( id int primary key auto_increment, userid int not null, roleid int not null ); --创建约束 alter table t_user_role add CONSTRAINT fk_userid foreign key (userid) REFERENCES t_user (id); alter table t_user_role add CONSTRAINT fk_roleid foreign key (roleid) REFERENCES t_role (id); --插入数据 insert into t_user_role select null,a.id, b.id from t_user a, t_role b where a.username = 'user' and b.name='普通用户'; insert into t_user_role select null,a.id, b.id from t_user a, t_role b where a.username = 'admin' and b.name='高级用户'; --创建角色--权限关联关系表(多对多) create table t_role_perm( id int primary key auto_increment, permid int not null, roleid int not null ); --创建约束 alter table t_role_perm add CONSTRAINT fk_perm_permid foreign key (permid) REFERENCES t_perm (id); alter table t_role_perm add CONSTRAINT fk_perm_roleid foreign key (roleid) REFERENCES t_role (id); --插入数据 insert into t_role_perm select null,a.id, b.id from t_role a, t_perm b where a.name = '普通用户' and b.name='ENTER_ORDINARY_PAGE'; insert into t_role_perm select null,a.id, b.id from t_role a, t_perm b where a.name = '高级用户' and b.name='ROLE_ENTER_HIGH_LEVEL_PAGE';
5 在spring security的配置文件中,有如下配置:
<authentication-manager alias="authenticationManager"> <!-- <authentication-provider user-service-ref="userDetailsManager"> --> <authentication-provider user-service-ref="userService"> <password-encoder hash="md5"> <salt-source user-property="username"/> </password-encoder> <!-- <password-encoder ref="passwordEncoder"> --> <!-- 用户名做为盐值 --> <!--<salt-source user-property="username" /> </password-encoder>--> </authentication-provider> </authentication-manager>
对于authentication-provider的配置有很多种,可以使用jdbc的配置,也可以使用service的,在此,我们使用service配置来实现用户的登陆和授权验证
6 在spring的配置文件中注册要使用的service
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"> <!-- 配置占位符 --> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location" > <value>WEB-INF/config/jdbc.properties</value> </property> </bean> <!-- 数据源 --> <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${JDBC.DRIVERNAME}"/> <property name="url" value="${JDBC.URL}"/> <property name="username" value="${JDBC.USERNAME}"/> <property name="password" value="${JDBC.PASSWORD}"/> </bean> <bean id="mySessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource" ref="myDataSource"/> <property name="packagesToScan"> <list> <value>main.model</value> </list> </property> <property name="hibernateProperties"> <value> hibernate.dialect=org.hibernate.dialect.MySQLDialect hibernate.show_sql=true hibernate.hbm2ddl.auto=update hibernate.cache.provider_class=org.hibernate.cache.NoCacheProvider </value> </property> </bean> <bean id="userDaoImpl" class="main.daoImpl.UserDaoImpl"> <property name="sessionFactory" ref="mySessionFactory"></property> </bean> <bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" /> <!-- 用户详细信息管理 : 数据源、用户缓存、启用用户组功能。 --> <bean id="userDetailsManager" class="org.springframework.security.provisioning.JdbcUserDetailsManager"> <property name="dataSource" ref="myDataSource" /> <!-- <property name="userCache" ref="userCache" /> --> </bean> <bean id="userService" class="main.service.UserService"> <property name="userDaoImpl" ref="userDaoImpl"/> </bean> <!-- spring security session-manager --> <bean id="concurrencyFilter" class="org.springframework.security.web.session.ConcurrentSessionFilter"> <property name="sessionRegistry" ref="sessionRegistry" /> <property name="expiredUrl" value="/timeout.jsp" /> </bean> <bean id="sessionAuthenticationStrategy" class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy"> <constructor-arg type="org.springframework.security.core.session.SessionRegistry" index="0" ref="sessionRegistry" /> <property name="maximumSessions" value="1" /> <property name="exceptionIfMaximumExceeded" value="true"></property> </bean> <bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl" /> </beans>
7 使用UserDetailsService做验证和授权,首先要实现UserDetails接口,以把我们从数据库查询到的数据包装后供spring security使用
package main.security; import java.util.ArrayList; import java.util.Collection; import main.model.Perm; import main.model.User; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.GrantedAuthorityImpl; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.userdetails.UserDetails; @SuppressWarnings("serial") public class UserDetail implements UserDetails { public UserDetail(User user) { this.username = user.getUsername(); this.password = user.getPassword(); this.authorities = new ArrayList<GrantedAuthority>(); for (Perm perm : user.getPerms()) { this.authorities.add(new GrantedAuthorityImpl(perm.getName())); } } private String username; private String password; private Collection<GrantedAuthority> authorities; public Collection<GrantedAuthority> getAuthorities() { return this.authorities; } public String getPassword() { return this.password; } public String getUsername() { return this.username; } public boolean isAccountNonExpired() { return true; } public boolean isAccountNonLocked() { return true; } public boolean isCredentialsNonExpired() { return true; } @Override public boolean equals(Object obj) { if (obj instanceof UserDetail) { UserDetail another = (UserDetail)obj; return this.getUsername().equals(another.getUsername()); } return super.equals(obj); } @Override public int hashCode() { return this.getUsername().hashCode(); } public boolean isEnabled() { return true; } }
在UserDetails中可以获取到当前用户的权限
8 实现UserDetailsService接口,实现验证和授权
package main.service; import java.util.List; import main.daoImpl.UserDaoImpl; import main.model.Perm; import main.model.User; import main.security.UserDetail; import org.springframework.dao.DataAccessException; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; public class UserService implements UserDetailsService { private UserDaoImpl userDaoImpl; public void setUserDaoImpl(UserDaoImpl userDaoImpl) { this.userDaoImpl = userDaoImpl; } public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { User user = this.userDaoImpl.findByName(username); if (user == null) { throw new UsernameNotFoundException("用户名错误!"); } //从数据库中获取当前用户拥有权限 List<Perm> permList = this.userDaoImpl.listPermByUser(user); user.setPerms(permList); return new UserDetail(user); } }
看到loadUserByUsername方法时,你可能会疑问,只是在验证用户名是否正确,并没验证密码,是的,此方法只验证用户名,返回值类为UserRetails,该接口有个getPassword()方法,实现该接口时只要把用户的密码在此方法中返回就行了,密码的验证由spring security 自己完成的
到此就是一个完整的基于用户,角色,权限管理的spring security项目了,有很多的具体细节没有讲到,我在此附上源码,有兴趣的可以自己跑跑一下!
相关推荐
**Spring Security 3.0.x 知识点详解** Spring Security 是一个强大的和高度可定制的身份验证和访问控制框架,广泛应用于Java企业级应用的安全管理。Spring Security 3.0.x 版本是该框架的一个重要里程碑,它提供了...
在3.0版本中,Spring Security 已经相当成熟,提供了丰富的特性来保障应用的安全性。 在开始使用Spring Security时,了解并正确引入必要的jar包是至关重要的。以下是你提供的压缩包文件中的关键组件: 1. **spring...
在Spring Security 3.0x中,配置"remember-me"服务主要包括以下几个步骤: 1. **依赖配置**:首先,确保你的项目依赖于Spring Security 3.0.x版本。在你的pom.xml或build.gradle文件中添加相应的依赖。 2. **配置...
thymeleaf-extras-springsecurity3 for integration with Spring Security 3.x thymeleaf-extras-springsecurity4 for integration with Spring Security 4.x Current versions: Version 3.0.2.RELEASE - for ...
如果你的项目已经使用了Spring 3.0.x,那么3.0.0版本可能是更兼容的选择;而3.1.3则提供了更多的改进和修复,如果兼容性不是问题,推荐使用这个版本。在提供的压缩包中,`spring-security-3.0.0.RELEASE.zip`包含了...
通过学习《Spring Security 3.x 官方文档》,开发者可以掌握如何在Spring应用中正确地配置和使用Spring Security,确保应用的安全性和稳定性。这份文档详尽地阐述了各种安全策略和技术,对于提升Java Web开发者的...
这部分涉及到了实际的SpringSecurity配置,如元素和元素的使用,用于定义安全规则和URL的访问权限。其中元素的pattern属性用于指定要拦截的URL模式,而access属性则用来指定哪些角色可以访问匹配的URL。此外,文档...
《spring-security3.0.rar》是一个包含Spring Security 3.0版本库的压缩文件,用户可以将其解压到项目的lib目录下,以便在项目中引用。3.0版本虽然较旧,但仍能提供基本的安全功能,如HTTP安全、基于角色的访问控制...
### Spring Security 3.0 入门与核心概念详解 #### 一、Spring Security简介 Spring Security 是一款功能强大且高度可定制的应用安全框架,它为基于 Java 的应用程序提供了全面的安全服务。尤其对于那些采用 ...
Springboot整合Spring security+Oauth2+JWT搭建认证服务器,网关,微服务之间权限认证及授权。 OAuth2是一个关于授权的开放标准,核心思路是通过各类认证手段(具体什么手段OAuth2不关心)认证用户身份,并颁发...
该存储库包含3个项目: thymeleaf-extras-springsecurity3与Spring Security 3.x集成thymeleaf-extras-springsecurity4用于与Spring Security 4.x集成thymeleaf-extras-springsecurity5与Spring Security 5.x集成...
Acegi Security在Spring Security 2.0版本之前被广泛使用,它为Web应用程序提供了细粒度的安全控制功能。通过Acegi Security,开发者可以轻松地实现基于角色的安全性,确保只有经过验证的用户才能访问特定资源。 ##...
结合《Spring MVC 3.0实战指南》,本书旨在帮助读者掌握Spring 3.x版本的核心特性和最佳实践,以便在现代Java应用开发中实现高效、可维护的解决方案。 Spring框架是Java领域中最广泛使用的轻量级框架之一,它提供了...
自 Spring Security 3.0 版本以来,该框架经历了多次重大改进和技术迭代。4.0 版本更是引入了许多新特性,进一步提升了安全性的同时简化了配置过程。 ##### 1.3 发行编号 Spring Security 4.0.1 是在 4.0 版本基础...