Spring MVC:MySQL和Hibernate的安全性

Spring有很多不同的模块。 所有这些对于具体目的都是有用的。 今天,我将讨论Spring Security。 该模块提供了灵活的方法来管理访问Web应用程序不同部分的许可。 在这篇文章中,我将研究Spring MVCHibernateMySQLSpring Security的集成。

任何Web应用程序的常规情况都是某些用户组之间的功能分离。 例如,具有“主持人”角色的用户可以编辑数据库中的现有记录。 一个用户
具有“管理员”角色的用户可以执行与具有“主持人”角色的用户相同的操作,并创建新记录。 在Spring MVC中,可以使用Spring Security来实现许可管理。

目标

作为示例,我将在Hibernate中使用示例Spring MVC应用程序。 用户及其角色将存储在数据库中。 MySQL将用作数据库。 我将创建三个表:用户,角色,user_roles。 您可能会猜到user_roles表是一个中间表 。 在应用程序中将扮演两个角色:主持人和管理员。 将有几个页面可供主持人和管理员访问。

制备

为了使Spring Security在项目中可用,只需在pom.xml文件中添加以下依赖项:

<!-- Spring Security --><dependency><groupid>org.springframework.security</groupid><artifactid>spring-security-core</artifactid><version>3.1.3.RELEASE</version></dependency><dependency><groupid>org.springframework.security</groupid><artifactid>spring-security-web</artifactid><version>3.1.3.RELEASE</version></dependency><dependency><groupid>org.springframework.security</groupid><artifactid>spring-security-config</artifactid><version>3.1.3.RELEASE</version></dependency>

我必须在数据库中创建三个表,并在其中插入几条记录。

CREATE TABLE `roles` (`id` int(6) NOT NULL AUTO_INCREMENT,`role` varchar(20) NOT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;CREATE TABLE `users` (`id` int(6) NOT NULL AUTO_INCREMENT,`login` varchar(20) NOT NULL,`password` varchar(20) NOT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;CREATE TABLE `user_roles` (`user_id` int(6) NOT NULL,`role_id` int(6) NOT NULL,KEY `user` (`user_id`),KEY `role` (`role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

这是角色和用户的代码:

INSERT INTO hibnatedb.roles (role) VALUES ('admin'), ('moderator');INSERT INTO hibnatedb.users (login, password) VALUES ('moder', '111111'), ('adm', '222222');INSERT INTO hibnatedb.user_roles (user_id, role_id) VALUES (1, 2), (2, 1);

主要部分

项目的完整结构具有以下结构:

由于您可以在GitHub上找到该项目,因此我将忽略当前主题之外的一些内容。 我想从每个Web项目的心脏开始,我的意思是web.xml文件。 Spring Security基于简单的过滤器,因此我需要在部署描述符中添加过滤器的声明:

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

现在是时候为用户和角色表创建实体了:

@Entity
@Table(name="users")
public class User {@Id@GeneratedValueprivate Integer id;private String login;private String password;@OneToOne(cascade=CascadeType.ALL)@JoinTable(name="user_roles",joinColumns = {@JoinColumn(name="user_id", referencedColumnName="id")},inverseJoinColumns = {@JoinColumn(name="role_id", referencedColumnName="id")})private Role role;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getLogin() {return login;}public void setLogin(String login) {this.login = login;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public Role getRole() {return role;}public void setRole(Role role) {this.role = role;}	}

@Entity
@Table(name="roles")
public class Role {@Id@GeneratedValueprivate Integer id;private String role;@OneToMany(cascade=CascadeType.ALL)@JoinTable(name="user_roles", joinColumns = {@JoinColumn(name="role_id", referencedColumnName="id")},inverseJoinColumns = {@JoinColumn(name="user_id", referencedColumnName="id")})private Set userRoles;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getRole() {return role;}public void setRole(String role) {this.role = role;}public Set getUserRoles() {return userRoles;}public void setUserRoles(Set userRoles) {this.userRoles = userRoles;}}

每个实体类都需要DAO和Service层。

public interface UserDAO {public User getUser(String login);}

@Repository
public class UserDAOImpl implements UserDAO {@Autowiredprivate SessionFactory sessionFactory;private Session openSession() {return sessionFactory.getCurrentSession();}public User getUser(String login) {List userList = new ArrayList();Query query = openSession().createQuery("from User u where u.login = :login");query.setParameter("login", login);userList = query.list();if (userList.size() > 0)return userList.get(0);elsereturn null;	}}

分别用于Role类:

public interface RoleDAO {public Role getRole(int id);}

@Repository
public class RoleDAOImpl implements RoleDAO {@Autowiredprivate SessionFactory sessionFactory;private Session getCurrentSession() {return sessionFactory.getCurrentSession();}public Role getRole(int id) {Role role = (Role) getCurrentSession().load(Role.class, id);return role;}}

服务层使用相同的对:

public interface UserService {public User getUser(String login);}

@Service
@Transactional
public class UserServiceImpl implements UserService {@Autowiredprivate UserDAO userDAO;public User getUser(String login) {return userDAO.getUser(login);}}

分别用于Role类:

public interface RoleService {public Role getRole(int id);}

@Service
@Transactional
public class RoleServiceImpl implements RoleService {@Autowiredprivate RoleDAO roleDAO;public Role getRole(int id) {return roleDAO.getRole(id);}}

以上只是机械的常规代码。 现在让我们研究Spring Security代码。 为了将Spring Security插入到项目中,我必须创建CustomUserDetailsS​​ervice类并实现UserDetailsS​​ervice接口。

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
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 com.sprsec.dao.UserDAO;@Service
@Transactional(readOnly=true)
public class CustomUserDetailsService implements UserDetailsService {@Autowiredprivate UserDAO userDAO;	public UserDetails loadUserByUsername(String login)throws UsernameNotFoundException {com.sprsec.model.User domainUser = userDAO.getUser(login);boolean enabled = true;boolean accountNonExpired = true;boolean credentialsNonExpired = true;boolean accountNonLocked = true;return new User(domainUser.getLogin(), domainUser.getPassword(), enabled, accountNonExpired, credentialsNonExpired, accountNonLocked,getAuthorities(domainUser.getRole().getId()));}public Collection getAuthorities(Integer role) {List authList = getGrantedAuthorities(getRoles(role));return authList;}public List getRoles(Integer role) {List roles = new ArrayList();if (role.intValue() == 1) {roles.add("ROLE_MODERATOR");roles.add("ROLE_ADMIN");} else if (role.intValue() == 2) {roles.add("ROLE_MODERATOR");}return roles;}public static List getGrantedAuthorities(List roles) {List authorities = new ArrayList();for (String role : roles) {authorities.add(new SimpleGrantedAuthority(role));}return authorities;}}

该类的主要目的是将应用程序的User类映射到Spring Security的User类。 这是Spring Security的杀手级功能之一。 这样,您可以使任何种类的Spring MVC应用程序适应Security模块的使用。

控制器和视图

有关Spring Security的最常见问题之一是如何创建自定义登录表单 。 答案很简单。 您需要使用该表单创建一个JSP文件,并在其中指定action属性()。

URL映射的大部分取决于spring-security.xml文件:

...<http auto-config="true"><intercept-url pattern="/sec/moderation.html" access="ROLE_MODERATOR"><intercept-url pattern="/admin/*" access="ROLE_ADMIN"><form-login login-page="/user-login.html" default-target-url="/success-login.html" authentication-failure-url="/error-login.html"><logout logout-success-url="/index.html"></logout></form-login></intercept-url></intercept-url></http><authentication-manager><authentication-provider user-service-ref="customUserDetailsService"><password-encoder hash="plaintext"></password-encoder></authentication-provider></authentication-manager>
...

如您所见,我为以下各项指定了URL:登录页面,成功登录后的默认页面,凭据无效情况下的错误页面。 我也声明了需要一些访问许可的URL。 最重要的是身份验证管理器的声明。 通过这种方式,Spring Security将使用数据库来识别用户及其角色。

控制器:

@Controller
public class LinkNavigation {@RequestMapping(value="/", method=RequestMethod.GET)public ModelAndView homePage() {return new ModelAndView("home");}@RequestMapping(value="/index", method=RequestMethod.GET)public ModelAndView indexPage() {return new ModelAndView("home");}@RequestMapping(value="/sec/moderation", method=RequestMethod.GET)public ModelAndView moderatorPage() {return new ModelAndView("moderation");}@RequestMapping(value="/admin/first", method=RequestMethod.GET)public ModelAndView firstAdminPage() {return new ModelAndView("admin-first");}@RequestMapping(value="/admin/second", method=RequestMethod.GET)public ModelAndView secondAdminPage() {return new ModelAndView("admin-second");}}

@Controller
public class SecurityNavigation {@RequestMapping(value="/user-login", method=RequestMethod.GET)public ModelAndView loginForm() {return new ModelAndView("login-form");}@RequestMapping(value="/error-login", method=RequestMethod.GET)public ModelAndView invalidLogin() {ModelAndView modelAndView = new ModelAndView("login-form");modelAndView.addObject("error", true);return modelAndView;}@RequestMapping(value="/success-login", method=RequestMethod.GET)public ModelAndView successLogin() {return new ModelAndView("success-login");}}

您可以在GitHub上看到的视图 。

请注意在WebAppConfig java类中添加@ImportResource(“ classpath:spring-security.xml”)。

摘要

我认为本文将帮助您深入了解Spring Security。 我在这里使用了Hibernate和MySQL,因为这样的技术组合在Internet上的其他教程中并不经常使用。 可能您注意到我在项目中使用了一些XML,这是因为当前尚无办法使用基于注释的方法来实现所有这些东西。

参考资料: Spring MVC:来自JCG合作伙伴 Alexey Zvolinskiy(来自Fruzenshtein的注释博客)的MySQL和Hibernate的安全性 。

翻译自: https://www.javacodegeeks.com/2013/05/spring-mvc-security-with-mysql-and-hibernate.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/368506.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python 离线 安装requests第三方库

一、介绍 requests是Python的一个HTTP客户端库&#xff0c;跟urllib&#xff0c;urllib2类似&#xff0c;不过requests的优势在于使用简单&#xff0c;相同一个功能&#xff0c;用requests实现起来代码量要少很多。毕竟官方文档都很直白的说&#xff1a; python的标准库urllib2…

JS分页条插件

目标 制作js分页导航jq插件,用于无刷新分页或者刷新分页 实现目标参考京东和天猫的分页条. 有四个固定按钮,前页码,后页码,首页,末页. 程序关键点在于计算中间页面的起止位置.逻辑是以当前页码为参照点,根据需要显示的页码按钮个数,计算参照点前后的页码数量. 当起止点小于1或者…

头同尾合十的算法_乘法速算之首同尾合十

两位数乘两位数中&#xff0c;有一种特殊情况不需要列竖式&#xff0c;可以直接说出答案&#xff0c;那就是“首同尾合十”——十位相同&#xff0c;个位数字之和是10。一、巧算方法前两位&#xff1a;十位数字(十位数字1)&#xff0c;后两位&#xff1a;个位相乘例如&#xff…

JavaFX逆运动学库2.0

这是第一篇讲解javafx-ik的基础教程&#xff0c; javafx-ik是JavaFX的逆运动学库。 该库的源代码可以从GitHub下载。 什么是 图1&#xff1a;单骨 骨骼是使用javafx-ik库进行逆运动学的基本基础。 骨骼具有一定长度和关节&#xff0c;骨骼可以围绕该关节旋转。 具有关节的一端…

html权重值_史上最全的web前端面试题汇总及答案HtmlCss(二)

作者&#xff1a;樱桃小丸子儿链接&#xff1a;https://www.jianshu.com/p/abadcc84e2a4HTML&CSSimg的alt和title的异同&#xff1f;**alt **是图片加载失败时&#xff0c;显示在网页上的替代文字&#xff1b;**title **是鼠标放上面时显示的文字,title是对图片的描述与进一…

解决问题SyntaxError: Unexpected token import

ES6语法的模块导入导出(import/export)功能,我们在使用它的时候&#xff0c;可能会报错&#xff1a; SyntaxError: Unexpected token import 语法错误&#xff1a;此处不应该出现import 我遇到的情况是import语法不识别导致的。在这里&#xff0c;有两种方法可以解决。 1: 使用…

使用Gradle的简单Spring MVC Web应用程序

除了我们现在将使用Spring MVC而不是原始servlet之外&#xff0c;该文章将与我们以前的文章Simple Gradle Web Application相似。 使用Gradle运行基本的Spring MVC应用程序确实很容易。 您可以在Github上下载本教程的源代码。 先决条件 安装Gradle 我们的基本项目结构将是&am…

tps波动很大的原因_花生价格小幅上涨,要突破6元大关?粮贩:还有很大距离...

花生是一种重要的油料作物&#xff0c;虽然并不是全国都种植&#xff0c;但在黄淮、长江流域&#xff0c;西北和东北等地区&#xff0c;均广泛种植&#xff0c;近期花生价格一直是农民朋友的关注点&#xff0c;从今年花生价格来看&#xff0c;自从花生上市后&#xff0c;价格起…

html css 基础(标签选择,分页,行和块元素)

&#xff08;1&#xff09;html标签选择 1、<a></a> 的功能有连接&#xff0c;下载&#xff0c;锚点 2、<span></span> 用来区分字体样式&#xff0c;<strong></strong>和<em></em>用来强调某段文字 3、如果是描述性的某段…

使用LDAP保护Java EE6中的Web应用程序

在上一篇文章中&#xff0c;我们解释了如何在通过传输层安全性&#xff08;TLS&#xff09;/安全套接字层&#xff08;SSL&#xff09;传输数据时保护数据。 现在&#xff0c;让我们尝试了解如何为使用LDAP服务器进行身份验证的基于JEE 6的Web应用程序应用安全机制。 目的&…

设计模式(二十二)------23种设计模式(14):解释器模式

使用频率&#xff1a;★☆☆☆☆ 一、什么是解释器模式 定义一些语法规则&#xff0c;然后定义一个解析器去解析该语法&#xff1b; 所谓解释器模式就是定义语言的文法&#xff0c;并且建立一个解释器来解释该语言中的句子。 在这里我们将语言理解成使用规定格式和语法的代码。…

【HTML】前端性能优化之CDN和WPO的比较

CDN通过将资源存储在更接近用户的位置&#xff0c;缩短到服务器的往返行程&#xff0c;加快页面加载时间来解决性能问题。WPO解决方案&#xff0c;如Radware的FastView&#xff0c;则在前端进行性能提升处理&#xff0c;使页面更有效地呈现在浏览器中。 “我已经使用了内容交付…

python自动化测试-D1-学习笔记之二

Jmeter 一、Jmeter连接数据库 1、打开Jmeter&#xff0c;在Jmeter—测试计划中添加mysql的jar包&#xff0c;见如下截图&#xff1a; 2、添加好jar包后&#xff0c;添加jdbc&#xff0c;并进行设置&#xff0c;如下图 3、添加JDBC Request&#xff0c;然后在JDBC Request中操作…

Android View 的滑动

一、View 的简介 View是所有可视化控件的基类&#xff0c;我们平时接触的所有的控件&#xff0c;比如说TextView,Button 等等都继承于View。View是Android 在视觉上的呈现&#xff0c;是界面层控件的一种抽象&#xff0c;可以是单个控件也可以是一组控件。 二、坐标系 1、Andro…

flask 检测post是否为空_使用Flask搭建一个校园论坛-4

在上一节中完成了注册功能的前期准备工作&#xff0c;在这一节内容中将完成用户注册、登录功能。1.知识预览在本届中将学习到以下内容的知识如何使用wtform来渲染表单如果使用flask-mail来发送邮件2.用户注册在前端中form表单是用的比较多的东西&#xff0c;我们可以使用wtform…

SQL Table 自动生成Net底层-生成数据操作Repository

生成接口类 public static string DataTableToBaseIService(string tableName, string nameSpace, string className){var table SqlTableHelper.GetSQLTableInfo(tableName);StringBuilder reval new StringBuilder();reval.AppendFormat(" using System; using…

自定义Spring命名空间使JAXB更容易

首先&#xff0c;让我大声说出来&#xff1a; Spring不再是XML繁重的了 。 事实上&#xff0c;如今&#xff0c;您可以使用大量注释&#xff0c; Java配置和Spring Boot来编写几乎没有XML或根本没有XML的Spring应用程序。 认真地停止谈论Spring和XML&#xff0c;这已经成为过去…

利用锚点再点事吧丨

上图 接着HTML代码&#xff1a; <div id"color"> <div id"red">红</div> <div id"yellow">黄</div> <div id"black">黑</div> <div id"green">绿</div> </div>…

javaweb笔记1

转载于:https://www.cnblogs.com/webdev8888/p/9164291.html

以太网数据帧的报尾封装字段是什么_16、90秒快速“读懂”数据包的封装、解封装...

数据转发过程概述数据包在相同网段内或不同网段之间转发所依据的原理基本一致。一、数据帧封装TCP封装(四层)当主机建立了到达目的地的TCP连接后&#xff0c;便开始对应用层数据进行封装。主机A会对待发送的应用数据首先执行加密和压缩等相关操作&#xff0c;之后进行传输层封装…