Spring MVC:MySQL和Hibernate的安全性

本文探讨如何在Spring MVC项目中集成Spring Security、Hibernate和MySQL,实现用户角色权限管理。通过创建用户、角色表并配置相关实体、服务层,以及自定义UserDetailsService,展示如何设置过滤器、登录表单及权限控制,为Web应用提供安全性。
摘要由CSDN通过智能技术生成

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
	@GeneratedValue
	private 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
	@GeneratedValue
	private 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 {

	@Autowired
	private 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);
		else
			return null;	
	}

}

分别用于Role类:

public interface RoleDAO {

	public Role getRole(int id);

}

@Repository
public class RoleDAOImpl implements RoleDAO {

	@Autowired
	private 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 {

	@Autowired
	private 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 {

	@Autowired
	private 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 {

	@Autowired
	private 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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值