- 浏览: 382007 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
fuchenggangs:
手动抛出异常后想要自动回滚@Transactional(rol ...
spring mvc 与JPA/Hibernate的整合示例 -
springdata_spring:
可以参考最新的文档:如何在eclipse jee中检出项目并转 ...
利用eclipse构建和部署maven工程 -
hzw2312:
好像这个事务不起作用呀!
@Transactional(rea ...
spring mvc 与JPA/Hibernate的整合示例 -
huhuhuhh:
类目清晰,感谢分享!
spring mvc 与JPA/Hibernate的整合示例 -
endual:
菜鸟问下,<!-- Spring Data Jpa配置 ...
spring mvc 与JPA/Hibernate的整合示例
这里在一个web工程中,通过三张表,实现用户、角色、权限的关系实现一个相对简单的权限系统。没有考虑对资源(URL)的控制
一、在web工程中加入springsecurity的支持,主要jar包
二、配置web容器:web.xml
三、配置spring : applicationContext-springsecurity.xml
四、增加自己定义的登录页面:login.jsp
五、增加权限类:User.java、Role.java、Privileage.java
1、User.java
2、Role.java
3、Privilege.java
以上三个类,实际上还需要两个中间表。为了方便我采用系统自动建表。即:
六、实现自定义的用户管理类:UserDetailsServiceImpl.java
七、初化数据
为了能让系统能快速运行起来,可直接在数据库中插入基本数据:
分别user、role、privilege表及其中间表中插入测试数据,建立起它们之间的关系。系统基本可以运行了。
八、小结
1、web.xml里的配置要把springsecurity的拦截配置在前面,否则会被struts2首先拦截并报找不到action的错误。
2、自定义登录页面中的url和用户名、密码属性的定义不能随意。springsecurity自带的过虑器(UsernamePasswordAuthenticationFilter)中有定义:
3、权限表(privilege)的数据必须有与springsecurity配置中的权限一致的值,用户才能获得授权,否则无法通过。
比如:
那么,privilege表中,要有一项为“USER“的权限名。才能访问”/*“下的资源。
一、在web工程中加入springsecurity的支持,主要jar包
二、配置web容器:web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" 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_2_5.xsd"> <!-- - Location of the XML file that defines the root application context - Applied by ContextLoaderListener. --> <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath:applicationContext.xml classpath:applicationContext-sec.xml <!-- classpath:applicationContext-common-business.xml classpath:applicationContext-common-authorization.xml classpath:applicationContext-security.xml --> </param-value> </context-param> <filter> <filter-name>localizationFilter</filter-name> <filter-class>org.springframework.web.filter.RequestContextFilter</filter-class> </filter> <filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>localizationFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter> <filter-name>struts2</filter-name> <filter-class> org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- - Loads the root application context of this web app at startup. - The application context is then available via - WebApplicationContextUtils.getWebApplicationContext(servletContext). --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <error-page></error-page> <session-config> <session-timeout>20</session-timeout> </session-config> <!-- 出错页面定义 --> <error-page> <exception-type>java.lang.Throwable</exception-type> <location>/commons/error.jsp</location> </error-page> <error-page> <error-code>500</error-code> <location>/commons/500.jsp</location> </error-page> <error-page> <error-code>404</error-code> <location>/commons/404.jsp</location> </error-page> <error-page> <error-code>403</error-code> <location>/commons/403.jsp</location> </error-page> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
三、配置spring : applicationContext-springsecurity.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:beans="http://www.springframework.org/schema/beans" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd"> <http auto-config="true"> <form-login login-page="/login.jsp"/> <intercept-url pattern="/login.jsp*" filters="none"/> <intercept-url pattern="/*" access="ROLE_USER" /><!-- 配置资源的权限的关系 --> <!-- <http-basic /> --> </http> <authentication-manager alias="authenticationManager"> <authentication-provider user-service-ref="userDetailService"> <!-- <user-service> <user authorities="ROLE_USER" name="guest" password="guest" /> </user-service> --> <password-encoder hash="plaintext"></password-encoder> </authentication-provider> </authentication-manager> <beans:bean id="userDetailService" class="com.harmony.cap.auth.service.UserDetailsServiceImpl"/> </beans:beans>
四、增加自己定义的登录页面: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>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> This is my JSP page. <br> <form name='f' action='${pageContext.request.contextPath }/j_spring_security_check' method='POST'> User:<input type='text' name='j_username' value=''> Password:<input type='password' name='j_password'/> <input name="submit" type="submit"/> <input name="reset" type="reset"/> </form> </body> </html>
五、增加权限类:User.java、Role.java、Privileage.java
1、User.java
package cn.ibeans.ssh.model; import java.sql.Blob; import java.util.ArrayList; import java.util.List; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; import javax.persistence.OrderBy; import javax.persistence.Table; import javax.persistence.Transient; import org.apache.commons.lang.builder.ToStringBuilder; import org.hibernate.annotations.Cache; import org.hibernate.annotations.CacheConcurrencyStrategy; import org.hibernate.annotations.Fetch; import org.hibernate.annotations.FetchMode; import cn.ibeans.common.utils.reflection.ConvertUtils; /** * 用户. * * 使用JPA annotation定义ORM关系. * 使用Hibernate annotation定义JPA 1.0未覆盖的部分. * * @author calvin */ @Entity //表名与类名不相同时重新定义表名. @Table(name = "SYS_USERS") //默认的缓存策略. //@Cache(usage = CacheConcurrencyStrategy.READ_WRITE) public class User extends IdEntity { private String loginId; private String password;//为简化演示使用明文保存的密码 private String name; private String email; private String resume; private Blob photo; private List<Role> roleList = new ArrayList();//有序的关联对象集合 //字段非空且唯一, 用于提醒Entity使用者及生成DDL. @Column(nullable = false, unique = true) public String getLoginId() { return loginId; } public void setLoginId(String loginId) { this.loginId = loginId; } @Column(name="password") public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Column(name="resume") public String getResume() { return resume; } public void setResume(String resume) { this.resume = resume; } @Column(name="photo") public Blob getPhoto() { return photo; } public void setPhoto(Blob photo) { this.photo = photo; } @Column(name="name") public String getName() { return name; } public void setName(String name) { this.name = name; } @Column(name="email") public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } //多对多定义 @ManyToMany //中间表定义,表名采用默认命名规则 @JoinTable(name = "SYS_USER_ROLE", joinColumns = { @JoinColumn(name = "USER_ID") }, inverseJoinColumns = { @JoinColumn(name = "ROLE_ID") }) //Fecth策略定义 @Fetch(FetchMode.SUBSELECT) //集合按id排序. @OrderBy("id") //集合中对象id的缓存. //@Cache(usage = CacheConcurrencyStrategy.READ_WRITE) public List<Role> getRoleList() { return roleList; } public void setRoleList(List<Role> roleList) { this.roleList = roleList; } /** * 用户拥有的角色名称字符串, 多个角色名称用','分隔. */ //非持久化属性. @Transient public String getRoleNames() { return "";//ConvertUtils.convertElementPropertyToString(roleList, "name", ", "); } /** * 用户拥有的角色id字符串, 多个角色id用','分隔. */ //非持久化属性. @Transient @SuppressWarnings("unchecked") public List<Long> getRoleIds() { return null;//ConvertUtils.convertElementPropertyToList(roleList, "id"); } @Override public String toString() { return ToStringBuilder.reflectionToString(this); } }
2、Role.java
package cn.ibeans.ssh.model; import java.util.ArrayList; import java.util.List; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; import javax.persistence.OrderBy; import javax.persistence.Table; import javax.persistence.Transient; import org.apache.commons.lang.builder.ToStringBuilder; import org.hibernate.annotations.Cache; import org.hibernate.annotations.CacheConcurrencyStrategy; import org.hibernate.annotations.Fetch; import org.hibernate.annotations.FetchMode; /** * 角色. * * 注释见{@link User}. * * @author calvin */ @Entity @Table(name = "SYS_ROLES") //@Cache(usage = CacheConcurrencyStrategy.READ_WRITE) public class Role extends IdEntity { private String name; private List<Privilege> privilegeList = new ArrayList();//Lists.newArrayList(); public Role() { } public Role(Long id, String name) { this.id = id; this.name = name; } @Column(nullable = false, unique = true) public String getName() { return name; } public void setName(String name) { this.name = name; } @ManyToMany @JoinTable(name = "SYS_ROLE_PRIVILEGE", joinColumns = { @JoinColumn(name = "ROLE_ID") }, inverseJoinColumns = { @JoinColumn(name = "PRIVILEGE_ID") }) @Fetch(FetchMode.SUBSELECT) @OrderBy("id") //@Cache(usage = CacheConcurrencyStrategy.READ_WRITE) public List<Privilege> getPrivilegeList() { return privilegeList; } public void setPrivilegeList(List<Privilege> privilegeList) { this.privilegeList = privilegeList; } @Transient public String getAuthNames() { return "";//ConvertUtils.convertElementPropertyToString(authorityList, "name", ", "); } @Transient @SuppressWarnings("unchecked") public List<Long> getAuthIds() { return null;//ConvertUtils.convertElementPropertyToList(authorityList, "id"); } @Override public String toString() { return ToStringBuilder.reflectionToString(this); } }
3、Privilege.java
package cn.ibeans.ssh.model; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; import javax.persistence.Transient; import org.apache.commons.lang.builder.ToStringBuilder; import org.hibernate.annotations.Cache; import org.hibernate.annotations.CacheConcurrencyStrategy; /** * 权限. * * 注释见{@link User}. * * @author calvin */ @Entity @Table(name = "SYS_PRIVILEGE") //@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) public class Privilege extends IdEntity { /** * SpringSecurity中默认的角色/授权名前缀. */ public static final String AUTHORITY_PREFIX = "ROLE_"; private String name; public Privilege() { } public Privilege(Long id, String name) { this.id = id; this.name = name; } @Column(nullable = false, unique = true) public String getName() { return name; } public void setName(String name) { this.name = name; } @Transient public String getPrefixedName() { return AUTHORITY_PREFIX + name; } @Override public String toString() { return ToStringBuilder.reflectionToString(this); } }
以上三个类,实际上还需要两个中间表。为了方便我采用系统自动建表。即:
<prop key="hibernate.hbm2ddl.auto">update</prop>
六、实现自定义的用户管理类:UserDetailsServiceImpl.java
package cn.ibeans.ssh.auth.service; import java.util.HashSet; import java.util.Set; import org.apache.log4j.Logger; 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.transaction.annotation.Transactional; import cn.ibeans.ssh.auth.model.Privilege; import cn.ibeans.ssh.auth.model.Role; import cn.ibeans.ssh.auth.model.User; /** * 实现SpringSecurity的UserDetailsService接口,实现获取用户Detail信息的回调函数. * * @author calvin */ @Transactional(readOnly = true) public class UserDetailsServiceImpl implements UserDetailsService { Logger logger = Logger.getLogger(this.getClass()); private AccountManager accountManager; /** * 获取用户Details信息的回调函数. */ public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { User user = accountManager.findUserByLoginName(username); if (user == null) { throw new UsernameNotFoundException("用户" + username + " 不存在"); } Set<GrantedAuthority> grantedAuths = obtainGrantedAuthorities(user); //-- mini-web示例中无以下属性, 暂时全部设为true. --// boolean enabled = true; boolean accountNonExpired = true; boolean credentialsNonExpired = true; boolean accountNonLocked = true; UserDetails userdetails = new org.springframework.security.core.userdetails.User(user.getLoginId(), user .getPassword(), enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, grantedAuths); logger.debug("用户详细信息已获得。"+userdetails.getUsername()+"/"+userdetails.getPassword()); return userdetails; } /** * 获得用户所有角色的权限集合. */ private Set<GrantedAuthority> obtainGrantedAuthorities(User user) { Set<GrantedAuthority> authSet = new HashSet<GrantedAuthority>(); for (Role role : user.getRoleList()) { for (Privilege privilege : role.getPrivilegeList()) { authSet.add(new GrantedAuthorityImpl(privilege.getPrefixedName())); } } return authSet; } @Autowired public void setAccountManager(AccountManager accountManager) { this.accountManager = accountManager; } }
七、初化数据
为了能让系统能快速运行起来,可直接在数据库中插入基本数据:
分别user、role、privilege表及其中间表中插入测试数据,建立起它们之间的关系。系统基本可以运行了。
八、小结
1、web.xml里的配置要把springsecurity的拦截配置在前面,否则会被struts2首先拦截并报找不到action的错误。
2、自定义登录页面中的url和用户名、密码属性的定义不能随意。springsecurity自带的过虑器(UsernamePasswordAuthenticationFilter)中有定义:
public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "j_username"; public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "j_password"; public static final String SPRING_SECURITY_LAST_USERNAME_KEY = "SPRING_SECURITY_LAST_USERNAME"; private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY; private String passwordParameter = SPRING_SECURITY_FORM_PASSWORD_KEY; private boolean postOnly = true; //~ Constructors =================================================================================================== public UsernamePasswordAuthenticationFilter() { super("/j_spring_security_check"); }
3、权限表(privilege)的数据必须有与springsecurity配置中的权限一致的值,用户才能获得授权,否则无法通过。
比如:
<http auto-config="true"> <form-login login-page="/login.jsp"/> <intercept-url pattern="/login.jsp*" filters="none"/> <intercept-url pattern="/*" access="ROLE_USER" /><!-- 配置资源的权限的关系 --> <!-- <http-basic /> --> </http>
那么,privilege表中,要有一项为“USER“的权限名。才能访问”/*“下的资源。
发表评论
-
spring mvc 与JPA/Hibernate的整合示例
2013-07-17 16:53 35979一、首先通过maven加入spring、jpa和hiberna ... -
【JPA】基础知识
2012-03-04 20:22 1031JPA是java编程领域的ORM标准。最著名的参考实现是hib ... -
JAXB的基本应用
2012-02-29 00:13 1314JAXB(Java API for XML Binding)是 ... -
log4j的应用与配置
2012-01-31 22:25 1171在java编程领域,log4j已经是事实上的日志输出工具。不但 ... -
springsecurity学习笔记之一:安全架构的理解
2012-01-20 09:45 1470计划将springsecurity的引入新的项目中。开始学习。 ... -
activeMO学习笔记二:发布和订阅
2012-01-16 14:57 1438其实学习activeMQ的初衷就是要找一个能够实现异步消息的发 ... -
activeMO学习笔记一:开始自己的第一个mq
2012-01-14 14:01 1527因为项目的需要,在构思系统的架构设计上,想到了ActiveMQ ... -
cxf学习笔记之传递附件
2012-01-12 09:34 4617cxf是jws的实现,上传二进制文件主要借助MTOM来实现,只 ... -
cxf学习笔记之传递复杂对象
2012-01-10 14:52 3727设计思路,创建一个人员注册的web服务。接受客户端传递的人员信 ... -
ie的进度条总也走不完
2011-01-11 21:06 1137多年前就发现跑着的系统中,时常看见ie的进度条总也走不完。但事 ... -
什么是工作流?
2010-12-29 18:53 933项目要用到工作流,给自己补一课。 就是“业务过程的部分或整体 ... -
特定环境下的应用服务器的时差问题
2010-04-02 10:59 1190最近遇到希望的问题。在window2008+weblogic1 ... -
给tomcat的Dos窗口命名
2010-01-07 14:04 3110做javaee开发,离不了web容器,tomcat可以说是最常 ... -
cxf学习笔记之结合spring创建客户端
2009-12-28 18:46 1535这个比较迷惑人。。。至少对我这个初学者来说是如此。后面解释原因 ... -
cxf学习笔记之结合spring创建服务端
2009-12-28 18:43 2140刚起步时实际上服务端是最简单的。 一、加入cxf支持 简单的说 ... -
cxf学些过程中的一些问题
2009-12-27 18:24 37651、 2009-12-27 18:19:02 org.apac ... -
数据源的两种配置
2009-10-09 10:27 1156开发的应用系统通常可以对数据源进行多种配置。 1、开发过程中往 ... -
常量类与属性文件在开发中的使用技巧
2009-08-13 16:48 1022开发中经常会将一些常用的或常修改的数据记录到常量类或属性文件中 ... -
过滤器在web开发中的应用
2009-04-07 15:53 1027在现在的web开发中,使用Filter来完成一些支撑性的工作是 ... -
mvn and ssh融合问题及解决办法
2009-03-27 09:32 3520通过maven融合ssh(struts2+spring2.5+ ...
相关推荐
Spring Security 基于数据库的权限管理配置
基于springboot+SpringSecurity的一款权限认证系统源码+数据库.zip基于springboot+SpringSecurity的一款权限认证系统源码+数据库.zip基于springboot+SpringSecurity的一款权限认证系统源码+数据库.zip基于springboot...
SpringBoot+SpringSecurity+JWT+MybatisPlus实现基于注解的权限验证,可根据注解的格式不同,做到角色权限控制,角色加资源权限控制等,粒度比较细化。 @PreAuthorize("hasAnyRole('ADMIN','USER')"):具有admin或...
本项目基于Spring,整合Spring的security模块,实现用户管理和权限控制,是一套较为通用的权限控制功能,主要内容如下: 1.登录,包括“记住我”的功能; 2.加密,存储的密码不采用明文,初始密码1234; 3.拦截器...
用STS(Spring Tool Suite)开发的,spring mvc + spring security 实现的最简单的登录系统,无数据库。
后端使用SpringBoot框架进行业务逻辑开发,利用Spring Security实现权限控制。数据库采用MySQL进行数据存储,使用MyBatis进行数据访问。 权限控制模块设计包括用户、角色和权限三个主要模块。用户模块用于管理用户...
基于Springboot和Spring security的校园疫情防控系统源码+数据库.zip基于Springboot和Spring security的校园疫情防控系统源码+数据库.zip基于Springboot和Spring security的校园疫情防控系统源码+数据库.zip基于...
springboot springsecurity动态权限控制,实现数据库动态管理菜单权限
开发基于Spring Boot和Spring Security的权限认证系统可以按照以下步骤进行: 1. 确定需求:明确权限认证系统的功能和特性,比如用户管理、角色管理、权限管理等。 2. 数据库设计:设计数据库表结构,包括用户表、...
SpringBoot+SpringSecurity整合示例代码,实现了从数据库中获取信息进行登录认证和权限认证。 本项目为idea工程,请用idea2019导入(老版应该也可以)。 本项目用户信息所需sql文件,在工程的resources文件夹下,...
项目自身的权限信息结合spring security 框架的实现。 本DEMO只包括从数据库读取登录认证信息,认证通过后 从数据库读取授权信息来控制用户的访问.权限元素包括 用户,角色,菜单以及这三者的关系。 本DEMO使用了...
Spring Security 把授权信息写入数据库
在开源的SpringSide上作权限控制的demo,附带数据库。分层清晰,设计合理,系统松散耦合。结合业界流行的安全框架精心设计开发。
本项目是一套基于springboot实现的图书管理系统,主要针对计算机相关专业的正在做bishe的学生和需要项目实战练习的Java学习者。 包含:项目源码、数据库脚本等,该项目可以直接作为bishe使用。 项目都经过严格调试,...
这是一款基于SpringBoot+SpringSecurity的RBAC权限管理系统。原本只想着做成基于SpringSecurity的权限管理系统,但随着功能的增加感觉有些刹不住车了,之后可能会往后台管理系统方向发展。无任何重度依赖,非常适合...
基于SpringSecurity+springMVC+mybatis+mysql实现。基于SpringSecurity权限控制的简单工程DEMO。maven构建,用户信息存储在mysq数据库中
基于 Spring boot 的个人博客系统设计与实现(源码+数据库)。介绍 基于SpringBoot的个人博客系统 ; 包含用户端-管理端 实现 博客展示、 归档、友链、关于等用户端功能; 实现登录、仪表盘、发布文章、文章管理...
该资源是springsecurity+oauth2+jwt实现的单点登录demo,模式为授权码模式,实现自定义登录页面和自定义授权页面。应用数据存在内存中或者存在数据库中(附带数据库表结构),token存储分为数据库或者Redis。demo...
spring boot +spring security +thymeleaf 实现简单权限+remember-me功能
Java语言开发的统一角色访问控制系统(Unified Role Access Control System),基于Spring Security 3实现的权限控制系统 程序框架版本说明:Spring MVC 3.0.6 + Spring Security 3.1.3 + Hibernate 3.6.10 运行...