本文是一个简单的基于用户,角色,权限的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项目了,有很多的具体细节没有讲到,我在此附上源码,有兴趣的可以自己跑跑一下!
相关推荐
早一段时间学习了springsecurity3.0 框架,在开始阶段不知道导入那些必需jar包,经过摸索,总结出来最精简的jar包
英文版本,主要对spring security 3.0.x 进行了介绍, 以及如何使用spring 的 安全架构来进行 web 开发.
SpringSecurity3.0.x官方参考文档(英文+中文双解版)
基于用户,角色,权限的spring_security完整项目 博文链接:https://abc08010051.iteye.com/blog/1995648
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 Security 3.x 官网文档 chm格式 (中文版) Spring+Security+3.x+Reference_CN.chm
这次发布的Spring Security-3.0.1 是一个bug fix 版,主要是对3.0 中存在的一些问题进 行修 正。文档中没有添加新功能的介绍,但是将之前拼写错误的一些类名进行了修正,建议开发 者以这一版本的文档为参考。 ...
该存储库包含3个项目: thymeleaf-extras-springsecurity3与Spring Security 3.x集成thymeleaf-extras-springsecurity4用于与Spring Security 4.x集成thymeleaf-extras-springsecurity5与Spring Security 5.x集成...
可以使用在身份提供者模式下支持SAML 2.0的所有产品(例如ADFS 2.0,Shibboleth,OpenAM / OpenSSO,Ping Federate,Okta)来连接Spring SAML Extension。 有关功能的详细列表以及对最新版本的访问,请访问。行为...
spring-framework-3.2.x版本源代码,不是jar包。 里面缺少springframework.security,我正在找中。。
实战中经常用到,简化接口文档,方便前后端联调
6.3 将Spring与Struts 1.x集成 220 6.3.1 问题 220 6.3.2 解决方案 220 6.3.3 工作原理 220 6.4 将Spring与JSF集成 226 6.4.1 问题 226 6.4.2 解决方案 226 6.4.3 工作原理 227 6.5 将Spring与DWR...
MagicErp是使用java语言开发,基于SpringBoot2.X架构体系构建的一套erp系统,主要包含采购管理、仓库管理、销售管理、商品管理、库存报表、基础配置和系统配置等功能,细节上包含采购入库、订单销售、出库发货、库存...
6.3 将Spring与Struts 1.x集成 220 6.3.1 问题 220 6.3.2 解决方案 220 6.3.3 工作原理 220 6.4 将Spring与JSF集成 226 6.4.1 问题 226 6.4.2 解决方案 226 6.4.3 工作原理 227 6.5 将Spring与DWR...
Spring security转换到Apache Shiro 把JSON的引用包从jackson切换成fastjson 数据库连接池使用Durid Tomcat从6.X升级到7.X(8.X对异步消息支持不是很好) 把所有JS放到页面底部 修改所有Dao,并使Dao继承...
g bower gulpnpm installbower install本地执行gulp serve产生分布gulp build2)后端Grails 3.0.4 [官方网站]( )| [REST文档]( ) Spring Security Plugin 3.0 [插件存储库]( )如何 : 提示:[gvm工具]( )是...
kyrieboot是一个Java EE企业级快速开发平台,基于(Spring Boot,Spring Security,MyBatisPlus,Thymeleaf,Layui,Vue)技术组合,内置模块如:角色用户,菜单权限,登录日志,系统监控等。 技术选型 1,系统环境 ...
- RabbitMQ 3.6.x+ - Maven3.0+ - ZipKinServer 3.7.0+ ## 功能 ### 商城功能 - 首页 - 专题列表、专题详情 - 分类列表、分类详情 - 品牌列表、品牌详情 - 新品首发、人气推荐 - 团购 - 搜索 - 商品详情、商品...
9、拓展插件10、分布式与微服务开发环境:开发工具IntelliJ IDEA、Navicat Premium后端技术Springboot2.x、SpringSecurity、Oauth2、JWT、mybatis-plus、activiti、Flutter、Mysql等前端技术Node.js 10+、Vue.js 2.6...
- 页面交互使用Vue2.x,极大的提高了开发效率 - 引入swagger文档支持,方便编写API接口文档 **数据权限设计思想** - 管理员管理、角色管理、部门管理,可操作本部门及子部门数据 - 菜单管理、定时任务、参数...