前言
本来是打算在上一篇SpringMVC+Hibernate上写的,结果发现上面那篇一起整合的,结果发现上一篇内容实在是太长了,就另起一篇,这篇主要是采用 Maven搭建Spring+SpringMVC+Hibernate+Security整合,而Spring+SpringMVC+Hibernate已经在上一篇介绍了,在这篇将不再重复写了,主要说明一下SpringSecurity3.2权限控制整合搭建,以及配置,使用注意事项等。
SpringSecurity的Api文档地址:查看
1、Maven映入SpringSecurity依赖包
在pom.xml中引入我们需要引入spring-security-core,spring-security-config,spring-security-taglibs三个包,如下
- <!-- spring-security -->
- <dependency>
- <groupId>org.springframework.security</groupId>
- <artifactId>spring-security-core</artifactId>
- <version>${security.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework.security</groupId>
- <artifactId>spring-security-config</artifactId>
- <version>${security.version}</version>
- </dependency>
- <dependency>
- <groupId>org.springframework.security</groupId>
- <artifactId>spring-security-taglibs</artifactId>
- <version>${security.version}</version>
- </dependency>
2、配置security的配置文件
我们新建一个配置文件(起名随意),我这儿就叫spring-security.xml,我现在定义了几个权限,权限信息表内容如下:
其中:管理用户和全部用户的权限将通过jsp中security标签配置,其他的通过spring-security.xml文件配置。
先贴出spring-security.xml的文件,详细配置含义我将做一个简单的说明:
- <span style="font-size:14px;"><?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:security="http://www.springframework.org/schema/security"
- 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-4.1.xsd
- http://www.springframework.org/schema/security
- http://www.springframework.org/schema/security/spring-security-3.2.xsd"
- default-lazy-init="true">
- <description>spring-security配置</description>
- <!-- 静态资源 -->
- <security:http pattern="/css/**" security="none" />
- <security:http pattern="/js/**" security="none" />
- <security:http pattern="/images/**" security="none" />
- <security:http>
- <security:intercept-url pattern="/user/save*"
- access="ROLE_添加用户" requires-channel="any" />
- <security:intercept-url pattern="/user/delete*"
- access="ROLE_删除用户" requires-channel="any" />
- <security:intercept-url pattern="/user/user*"
- access="ROLE_浏览用户" requires-channel="any" />
- <security:intercept-url pattern="/user/update*"
- access="ROLE_修改用户" requires-channel="any" />
- <security:session-management>
- <security:concurrency-control
- expired-url="/login/login.htmls?repeat=true" max-sessions="1"
- error-if-maximum-exceeded="true" />
- </security:session-management>
- <security:form-login login-page="/login/login.htmls"
- authentication-failure-url="/login/login.htmls?error=true"
- default-target-url="/user/main.htmls" always-use-default-target='true'
- username-parameter="nickName" password-parameter="nickPassword" />
- <security:logout invalidate-session="true"
- logout-success-url="/login/login.htmls?logout=true" />
- </security:http>
- <!-- 认证配置 自定义认证实现UserDetailsService接口 -->
- <security:authentication-manager>
- <security:authentication-provider
- user-service-ref="userDetailsService">
- <!-- 配置密码加密方式 -->
- <security:password-encoder hash="md5" />
- </security:authentication-provider>
- </security:authentication-manager>
- <bean id="userDetailsService" class="org.andy.work.service.impl.UserDetailsServiceImpl" />
- </beans></span>
其中:我们配置了静态文件管理,session对话管理,登录管理,注销配置,权限配置,自定义数据表权限认证配置。
2.1、静态文件管理
我们对于css,image,js这些不用权限拦截。
2.2、session对话管理
session管理max-sessions="1"配置了最多有一个用户登录,(在wab.xml还要添加如下:)
- <span style="font-size:14px;"><!-- spring-security 管理session配置 -->
- <listener>
- <listener-class>
- org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
- </listener></span>
error-if-maximum-exceeded="true" 值为true时,若果有一个用户登录,第二个用户无法登陆,
值为false时,若果有一个用户已经登录,下一个用户登录将踢掉上一个用户。
自然在session-manager中我们可以配置session失效时,跳转的url如,invalid-session-url="/invalidSession.jsp",如果session失效时,刷新将跳转到invalidSession.jsp页面。
2.3、登录管理
通过security:form-login配置登录,login-page为登录跳转的url,authentication-failure-url为登录失败时的url(次url可以不存在),
username-parameter和password-parameter为登录表单是用户名和密码,如果不写默认为j_password和j_username
login-processing-url:为登录时表单action跳转的url,如果不填写默认为 j_spring_security_check。
2.4、注销管理
通过security:logout标签配置注销,invalidate-session:注销时session是否失效。logout-success-url:注销成功后跳转的地址。
logout-url:为注销的url,如果不填写,则默认为j_spring_security_logout
2.5、权限配置
security:intercept-url为要拦截权限认证的的url,pattern为拦截的正则匹配url,access:所需的权限,可以是一个权限组,用逗号隔开,requires-channel:拦截http还是https的,如果两个都拦截用any。
2.6、配置自定义的权限认证机制
通过我们数据库的权限表信息,我们自定义权限认证机制,需要我们实现UserDetailsService接口,配置用户密码的加密方式。
security:password-encoder:配置密码加密规则。
3、web.xml容器配置
- <span style="font-size:14px;"> <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>
- classpath:spring.xml
- classpath:spring-hibernate.xml
- classpath:spring-security.xml
- </param-value>
- </context-param>
- <!-- Spring-Security filter 最好配置在控制层filter的前面 -->
- <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>
- <!-- spring-security 管理session配置 -->
- <listener>
- <listener-class>
- org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
- </listener></span>
配置了加载的spring-security文件,security拦截的filter,以及security的session监听。
4、自定义认证,实现UserDetailsService接口
UserDetailsServiceImpl如下:
- <span style="font-size:14px;">package org.andy.work.service.impl;
- import java.util.HashSet;
- import java.util.Set;
- import org.andy.work.dao.UserDao;
- import org.andy.work.entity.AcctAuthority;
- import org.andy.work.entity.AcctRole;
- import org.andy.work.entity.AcctUser;
- import org.apache.log4j.Logger;
- 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;
- /**
- * 创建时间:2015-2-9 下午5:24:44
- *
- * @author andy
- * @version 2.2
- * <p>
- * 描述: 实现SpringSecurity的UserDetails接口 自定义认证
- */
- public class UserDetailsServiceImpl implements UserDetailsService {
- private static final Logger LOGGER = Logger
- .getLogger(UserDetailsServiceImpl.class);
- // 注入查询User的dao层
- @Autowired
- private UserDao userDao;
- @Override
- public UserDetails loadUserByUsername(String username)
- throws UsernameNotFoundException {
- LOGGER.info("认证用户:" + username);
- // 查询数据库获取改用户的信息
- AcctUser acctUser = userDao.findByNickName(username);
- if (null == acctUser) {
- throw new UsernameNotFoundException("用户:" + username + "不存在");
- }
- Set<GrantedAuthority> authorities = getAuthorities(acctUser);
- // 将没有使用到的属性设置为true
- UserDetails userDetails = new User(acctUser.getNickName(),
- acctUser.getNickPassword(), true, true, true, true, authorities);
- return userDetails;
- }
- // 获得用户所有角色的权限
- private Set<GrantedAuthority> getAuthorities(AcctUser acctUser) {
- Set<GrantedAuthority> authoritySet = new HashSet<GrantedAuthority>();
- // 默认所有的用户有"浏览用户"的权利
- authoritySet.add(new SimpleGrantedAuthority("ROLE_浏览用户"));
- // 依次添加
- if (null != acctUser.getAcctRoles()
- && acctUser.getAcctRoles().size() > 0)
- for (AcctRole role : acctUser.getAcctRoles()) {
- if (null != role.getAcctAuthorities()
- && role.getAcctAuthorities().size() > 0)
- for (AcctAuthority authority : role.getAcctAuthorities()) {
- authoritySet.add(new SimpleGrantedAuthority(authority
- .getPrefixedName()));
- }
- }
- return authoritySet;
- }
- }
- </span>
涉及到的AcctUser,AcctRole,AcctAuthority类我就不贴了,不然一大把,我会提供源码。
5、Security的认证错误提示
我们可以通过sessionScope.SPRING_SECURITY_LAST_EXCEPTION.message获取认证错误。
6、Security获取session中的用户名和用户信息
security将用户信息存放在session中,可以通过以下两种获得:
6.1、后台获取
- <span style="font-size:14px;"> //获取security的上下文
- SecurityContext securityContext = SecurityContextHolder.getContext();
- //获取认证对象
- Authentication authentication = securityContext.getAuthentication();
- //在认证对象中获取主体对象
- Object principal = authentication.getPrincipal();
- String username = "";
- if(principal instanceof UserDetails){
- username = ((UserDetails) principal).getUsername();
- }else {
- username = principal.toString();
- }</span>
6.1、前台获取
先引入security的标签库:
- <span style="font-size:14px;"><%@taglib prefix="security" uri="http://www.springframework.org/security/tags"%></span>
在查看:
- <span style="font-size:14px;"><security:authentication property="name"/></span>
7、前台标签授权
通过security:authorize标签设置权限,其有三种属性分别如下:
ifAnyGranted::只有当前用户拥有所指定的权限中的一个的时候,就能显示标签内部的内容(相当于“或”的关系)
ifAllGranted:只有当前用户拥有所指定的权限时,才显示标签的内容(相当于“与”的关系)
ifNotGranted: 没有指定的权限的时候,显示标签内容(相当于“非”的关系)
自然也可以通过method限制是那种http的请求(http的请求有8种:- GET - DELETE - HEAD - OPTIONS - POST - PUT - PATCH - TRACE)。
8、后台Controller
LoginController
- <span style="font-size:14px;"><span style="font-size:14px;">package org.andy.work.controller;
- import org.andy.work.entity.AcctUser;
- import org.apache.log4j.Logger;
- import org.springframework.stereotype.Controller;
- import org.springframework.validation.Errors;
- import org.springframework.web.bind.annotation.ModelAttribute;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestParam;
- /**
- * 创建时间:2015-2-10 下午9:23:34
- *
- * @author andy
- * @version 2.2 描述:
- */
- @Controller
- @RequestMapping("/login")
- public class LoginController {
- private static final Logger LOGGER = Logger
- .getLogger(LoginController.class);
- @RequestMapping("/login")
- public String login(@ModelAttribute AcctUser acctUser,
- @RequestParam(required = false) Boolean logout,
- Errors errors
- ) {
- LOGGER.info("login");
- if(null != logout){
- errors.reject("msg", "已经安全退出");
- }
- return "/login/login";
- }
- }</span>
- </span>
UserController类
- <span style="font-size:14px;">package org.andy.work.controller;
- import java.util.List;
- import org.andy.work.entity.AcctUser;
- import org.andy.work.service.UserService;
- import org.apache.log4j.Logger;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.security.core.Authentication;
- import org.springframework.security.core.context.SecurityContext;
- import org.springframework.security.core.context.SecurityContextHolder;
- import org.springframework.security.core.userdetails.UserDetails;
- import org.springframework.stereotype.Controller;
- import org.springframework.ui.ModelMap;
- import org.springframework.web.bind.annotation.PathVariable;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.ResponseBody;
- /**
- * 创建时间:2015-2-7 上午11:49:00
- * @author andy
- * @version 2.2
- * 描述: 用户Controller
- */
- @Controller
- @RequestMapping("/user")
- public class UserController {
- private static final Logger LOGGER = Logger.getLogger(UserController.class);
- @Autowired
- private UserService userService;
- @RequestMapping("/showInfo/{userId}")
- public String showUserInfo(ModelMap modelMap, @PathVariable String userId){
- LOGGER.info("查询用户:" + userId);
- AcctUser userInfo = userService.load(userId);
- modelMap.addAttribute("userInfo", userInfo);
- return "/user/showInfo";
- }
- @RequestMapping("/showInfos")
- public @ResponseBody List<AcctUser> showUserInfos(){
- LOGGER.info("查询用户全部用户");
- List<AcctUser> userInfos = userService.findAll();
- return userInfos;
- }
- @RequestMapping("/main")
- public String main(ModelMap modelMap){
- LOGGER.info("显示主页面");
- //后台获取security保存的session中的用户信息
- //获取security的上下文
- SecurityContext securityContext = SecurityContextHolder.getContext();
- //获取认证对象
- Authentication authentication = securityContext.getAuthentication();
- //在认证对象中获取主体对象
- Object principal = authentication.getPrincipal();
- String username = "";
- if(principal instanceof UserDetails){
- username = ((UserDetails) principal).getUsername();
- }else {
- username = principal.toString();
- }
- modelMap.addAttribute("username", username);
- return "/user/main";
- }
- @RequestMapping("/manage")
- public String manage(ModelMap modelMap){
- LOGGER.info("显示主页面");
- modelMap.addAttribute("msg", "manage");
- return "/user/option";
- }
- @RequestMapping("/save")
- public String save(ModelMap modelMap){
- LOGGER.info("保存");
- modelMap.addAttribute("msg", "save");
- return "/user/option";
- }
- @RequestMapping("/update")
- public String update(ModelMap modelMap){
- LOGGER.info("修改");
- modelMap.addAttribute("msg", "update");
- return "/user/option";
- }
- @RequestMapping("/delete")
- public String delete(ModelMap modelMap){
- LOGGER.info("删除");
- modelMap.addAttribute("msg", "delete");
- return "/user/option";
- }
- }
- </span>
9、前台
login.jsp
- <span style="font-size:14px;"><%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
- <%@taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
- <%@taglib prefix="spring" uri="http://www.springframework.org/tags"%>
- <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
- <%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
- <%
- String path = request.getContextPath();
- String basePath = request.getScheme() + "://"
- + request.getServerName() + ":" + request.getServerPort()
- + path + "/";
- %>
- <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
- <html>
- <head>
- <base href="<%=basePath%>" />
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <title>login</title>
- </head>
- <body>
- <div>${sessionScope.SPRING_SECURITY_LAST_EXCEPTION.message}</div>
- <form:form action="j_spring_security_check" modelAttribute="acctUser" method="post">
- <form:errors path="*" cssStyle="color:red;" />
- <br />
- 用户:<form:input path="nickName" />
- <br />
- 密码:<form:password path="nickPassword" />
- <br />
- <form:button>登录</form:button>
- </form:form>
- </body>
- </html></span>
main.jsp
- <span style="font-size:14px;"><%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
- <%@taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
- <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
- <%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
- <%@taglib prefix="security" uri="http://www.springframework.org/security/tags"%>
- <%
- String path = request.getContextPath();
- String basePath = request.getScheme() + "://"
- + request.getServerName() + ":" + request.getServerPort()
- + path + "/";
- %>
- <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
- <html>
- <head>
- <base href="<%=basePath%>" />
- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
- <title>login</title>
- </head>
- <body>
- welcome! <security:authentication property="name"/>
- <br/>
- 后台获取用户名:${username }
- <div style="border: 1px; "><a target="_blank" href="j_spring_security_logout">注销</a></div>
- <br/>
- <security:authorize ifAnyGranted="ROLE_浏览用户">
- <div>
- <a target="_blank" href="user/showInfo.htmls">全部用户</a>
- </div>
- </security:authorize>
- <security:authorize ifAllGranted="ROLE_管理用户">
- <div>
- <a target="_blank" href="user/manage.htmls">管理用户</a>
- </div>
- </security:authorize>
- <div>
- <a target="_blank" href="user/save.htmls">添加用户</a>
- </div>
- <div>
- <a target="_blank" href="user/update.htmls">修改部用户</a>
- </div>
- <div>
- <a target="_blank" href="user/delete.htmls">删除用户</a>
- </div>
- </body>
- </html></span>
10、测试
现在andy用户拥有“浏览用户”和“添加用户”权限
用户密码错误时:
正确密码登陆后:
点击添加用户,正确跳转。如下:
点击全部用户,无权限提示。
11、Spring security自定义认证错误提示
首先,拷贝spring-security-core写的messages_zh_CN.properties国际化文件,放到项目的src/main/resources目录中
修改对应的提示,按照我们自己的需求,我命名为messages.properties
其次, 我们需在spring的配置文件中添加如下内容:
- <span style="font-size:14px;"><span style="font-size:14px;"> <!-- 定义上下文返回的消息的国际化 -->
- <bean id="messageSource"
- class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
- <property name="basename" value="classpath:messages" />
- </bean>
- <bean id="localeResolver"
- class="org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver" /></span></span>
ok,Maven搭建Spring+Hibernate+security整合完毕。
后续
遗留问题,通用的重写security提示信息,其他的都能国际化汉语提示,但是
唯独
ConcurrentSessionControlStrategy.exceededAllowed=\u5DF2\u7ECF\u6709 {0} \u4E2A\u7528\u6237\u767B\u5F55\uFF0C\u4E0D\u80FD\u91CD\u590D\u767B\u5F55
我修改重复登录提示时,还是security原来自带的提示,如下:
希望又遇到的共同留言探讨。
相关推荐
**Spring Security新手入门级Maven实例详解** Spring Security是一个强大且高度可定制的身份验证和访问控制框架,用于Java和Java EE应用。它为应用程序提供了全面的安全解决方案,包括用户认证、授权以及安全配置。...
通过 Maven 搭建的 Spring+MyBatis 项目,可以充分利用这两个框架的优势,简化开发工作,提高代码可维护性和可扩展性。同时,Maven 的自动化构建能力有助于团队协作和持续集成。在实际项目中,还应注意遵循良好的...
SpringBoot + Spring Security 基本使用及个性化登录配置详解 Spring Security 是一个功能强大且灵活的安全框架,它提供了认证、授权、攻击防护等功能。SpringBoot 是一个基于 Spring 框架的框架,它提供了很多便捷...
在开始配置之前,确保你的项目已经集成了Spring Boot,因为Spring Security与Spring Boot的集成非常方便。 1. **添加依赖** 在`pom.xml`或`build.gradle`文件中,你需要引入Spring Security的依赖。对于Maven用户...
1. **添加依赖**:在 Maven 或 Gradle 项目中添加 Spring Security 相关依赖。 2. **配置 Security 配置类**:创建一个继承自 `WebSecurityConfigurerAdapter` 的配置类,重写 `configure(HttpSecurity http)` 方法...
### Spring-Security安全权限管理手册知识点详解 #### 一、Spring Security简介与选择原因 **Spring Security** 是一个强大的和高度可定制的身份验证和访问控制框架。它为开发者提供了多种安全相关的服务,使得...
**Spring Security集成CAS客户端实例详解** 在Web应用中,安全是至关重要的,Spring Security和CAS(Central Authentication Service)是两种广泛使用的安全框架。本实例旨在展示如何将Spring Security与CAS结合,...
二、renren-security 3.2详解 1. **系统架构**:renren-security基于Spring Boot和Spring Security进行构建,提供了微服务化的权限管理平台。它支持JWT(JSON Web Token)认证,实现无状态的API访问。 2. **权限控制...
### Spring Security 全套入门到项目实战课程知识点详解 #### 一、Spring Security 概述 **1.1 Spring Security 介绍** - **定义**: Spring Security 是一款基于 Spring 框架的身份认证(Authentication)与用户...
通过以上内容,读者将对Spring Security有一个全面的理解,能够搭建起基本的Spring Security框架并应用于实际项目中,为Web应用提供坚实的安全保障。在后续的学习中,可以深入研究Spring Security的高级特性,如...
### Spring Security 4 帮助文档核心知识点详解 #### 一、Spring Security 简介 ##### 1.1 什么是 Spring Security? Spring Security 是一个功能强大的安全框架,为基于 Java 的应用程序提供了认证...
**Spring Boot Maven Web 完整项目框架详解** Spring Boot 是由 Pivotal 团队提供的全新框架,其设计目标是用来简化新 Spring 应用的初始搭建以及开发过程。它集成了大量的常用组件,如数据源、JPA、WebSocket、...
《Spring Security HelloWorld详解》 Spring Security 是一个强大的和高度可定制的身份验证和访问控制框架,广泛应用于Java EE和Spring应用程序中。本篇文章将基于“spring security - helloWorld”项目,探讨...
Spring Security 基于 JWT 实现 SSO 单点登录详解 基于 Spring Security 框架和 JWT(JSON Web Token)技术,可以实现 SSO(Single Sign-On)单点登录系统。SSO 是一种常见的身份验证机制,允许用户使用同一个...
这些依赖可以通过Maven或Gradle进行管理,确保项目中已经正确配置了这些依赖。 ##### 2. Web.xml配置 为了使Spring Security能够在Web环境中正常工作,需要在`web.xml`中配置一个名为`springSecurityFilterChain`...
在配置Spring Security之前,需要先建立一个maven多模块工程,spring-security是父模块,spring-security-browser是处理浏览器相关的授权认证,最终作为demo的一个jar依赖,spring-security-core是一些授权认证的...
在实际开发中,SSM框架的配置会因项目需求而有所不同,例如添加缓存支持、安全框架(Spring Security)或任务调度(Spring Task)等。通过学习和实践SSM的配置搭建,开发者能够更好地理解和掌握Java Web开发的核心...
### 不错的Spring Security例子详解 #### 一、Spring Security简介 Spring Security 是一款功能强大的安全框架,它为Java应用提供了认证(Authentication)和授权(Authorization)服务。它能够帮助开发者构建安全...
- **创建项目**:首先创建一个名为 `spring-security-demo` 的 Maven 工程,并在 `pom.xml` 文件中添加必要的 Spring 和 Spring Security 相关依赖。 - **配置 Spring Security**:在 Spring 配置文件中定义 ...
1. **添加依赖**:在项目中引入Spring Security的依赖,这通常通过Maven或Gradle完成。例如,在Maven的pom.xml中,添加如下依赖: ```xml <groupId>org.springframework.security <artifactId>spring-security-...