在使用Spring Security配置Web应用之前,首先要准备一个基于Maven的Spring框架创建的Web应用(Spring MVC不是必须的),本文的内容都是基于这个前提下的。

pom.xml添加依赖

除了Spring框架本身的一些依赖包,还需要在pom.xml中添加Spring Security的依赖包:

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>4.0.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>4.0.2.RELEASE</version>
</dependency>

入门环境配置

要想使用Spring Security,首先需要在web.xml配置一个过滤器,注意过滤器的filter-name必须是springSecurityFilterChain

1
2
3
4
5
6
7
8
<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配置文件,并将这个文件添加到Spring Application Context中。下面是一个最基本的Spring Security配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="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.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd">

<http use-expressions="false">
<!-- 访问所有页面都需要有USER权限 -->
<intercept-url pattern="/**" access="ROLE_USER" />
<!-- 登录功能 -->
<form-login />
<!-- 登出功能 -->
<logout />
</http>

<authentication-manager>
<authentication-provider>
<user-service>
<!-- 这里创建两个用户,可以通过用户名密码登录 -->
<user name="jimi" password="jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
<user name="bob" password="bobspassword" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>

</beans:beans>

只需完成以上两个配置,启动服务器,用浏览器打开这个Web应用的任意一个页面,都会跳转到一个登录页,这个登录页面是Spring Security自动生成的。
Spring
Security默认登录页面

在登录页面输入错误的用户名密码,就会登录失败并有提示。输入正确的用户名密码,则登录成功,就可以进入Web应用的页面。一个最简单的基于Spring Security的Web应用已经完成!

指定登录页面

由于Spring Security默认的登录页面非常简陋,一般不会直接使用,通常会指定一个自定义的登录页面,例如指定一个自己的登录页/login.jsp

1
2
3
4
5
6
7
8
9
10
<http use-expressions="false">
<!-- 登录页面不需要控制权限 -->
<intercept-url pattern="/login.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<!-- 访问其他所有页面都需要有USER权限 -->
<intercept-url pattern="/**" access="ROLE_USER" />
<!-- 配置登录页面地址login-page、登录失败后的跳转地址authentication-failure-url -->
<form-login login-page='/login.jsp' authentication-failure-url='/login.jsp?error' />
<!-- 登出功能 -->
<logout />
</http>

自定义的登录页面jsp中的登录表单:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<c:url value="/login" var="loginUrl" />
<form action="${loginUrl}" method="post">
<c:if test="${param.error != null}">
<p>Invalid username and password.</p>
</c:if>
<c:if test="${param.logout != null}">
<p>You have been logged out.</p>
</c:if>
<p>
<label for="username">Username</label>
<input type="text" id="username" name="username" />
</p>
<p>
<label for="password">Password</label>
<input type="password" id="password" name="password" />
</p>
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
<button type="submit" class="btn">Log in</button>
</form>

登录表单提交的页面地址是/login,method是POST请求,登录请求需要提交usernamepassword两个参数。为了安全,防止恶意的CSRF攻击,Spring Security需要校验form表单中的hidden域提交的内容。

登出

Spring Security配置文件中的<logout />用于处理登出。

页面中的登出按钮:

1
2
3
4
5
<c:url value="/logout" var="logoutUrl" />
<form action="${logoutUrl}" method="post">
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
<input type="submit" value="退出" />
</form>

登出请求地址/logout,method是POST请求。

登录用户信息从数据库获取

上文的登录用户的用户名、密码、ROLE都是配置在Spring Security的xml配置文件中的,在实际使用中,一般不会将用户信息直接配置在xml文件中,而是通过其他方式获取,例如数据库。

Spring Security提供了一个便捷的方式通过数据库获取用户信息,即org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl,它是org.springframework.security.core.userdetails.UserDetailsService接口的一个实现类,只要配置相关的DataSource和SQL语句就能从数据库获取到用户信息:

1
2
3
4
5
6
7
8
<authentication-manager>
<authentication-provider user-service-ref='userDetailsService' />
</authentication-manager>
<beans:bean id="userDetailsService" class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
<beans:property name="dataSource" ref="dataSource"/>
<beans:property name="usersByUsernameQuery" value="select username, password, true from t_user where username = ?" />
<beans:property name="authoritiesByUsernameQuery" value="select username, role from t_user_role where username = ?" />
</beans:bean>

以上配置还可以简化为:

1
2
3
4
5
6
7
<authentication-manager>
<authentication-provider>
<jdbc-user-service data-source-ref="dataSource"
users-by-username-query="select username, password, true from t_user where username = ?"
authorities-by-username-query="select username, role from t_user_role where username = ?" />
</authentication-provider>
</authentication-manager>

登录用户信息通过其他方式获取

如果用户信息的来源并不是数据库,那么就需要自己实现org.springframework.security.core.userdetails.UserDetailsService接口的loadUserByUsername方法,即通过用户名获取用户信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class UserDetailsServiceImpl implements UserDetailsService {

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 以下可以替换成用其他方式获取用户信息
if(username.equals("xxg")) {
Collection<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();
SimpleGrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER");
auths.add(authority);
User user = new User(username, "123456", auths);
return user;
} else {
throw new UsernameNotFoundException("用户不存在");
}
}
}

将该实现类配置在Spring Security配置文件中:

1
2
3
4
<authentication-manager>
<authentication-provider user-service-ref='userDetailsService' />
</authentication-manager>
<beans:bean id="userDetailsService" class="com.xxg.UserDetailsServiceImpl" />

密码加密

明文保存密码通常是不安全的,在Spring Security中可以配置密码的加密方法。下面以MD5加密密码为例。

针对密码加密,Spring Security提供了org.springframework.security.crypto.password.PasswordEncoder接口。我们需要实现PasswordEncoder接口,实现我们自定义的加密方法,这样Spring Security在接收到用户登录请求后,会调用这个实现类,从而判断密码是否正确:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class PasswordEncoderImpl implements PasswordEncoder {

@Override
public String encode(CharSequence rawPassword) {
try {
// MD5加密密码
return DigestUtils.md5DigestAsHex(rawPassword.toString().getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
}

@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
return encode(rawPassword).equals(encodedPassword);
}
}

在Spring Security配置文件中配置上面的实现类:

1
2
3
4
5
6
7
<authentication-manager>
<authentication-provider>
<password-encoder ref="passwordEncoder" />
...
</authentication-provider>
</authentication-manager>
<beans:bean id="passwordEncoder" class="com.xxg.PasswordEncoderImpl" />

配置不受Spring Security管理的URL

如果Web应用中有某些URL不需要被Spring Security管理,例如一些静态文件,或者无需登录即可查看的页面,可以对这些URL配置security="none"

1
2
3
4
5
6
7
8
<http pattern="/resources/css/**" security="none"/>
<http pattern="/resources/images/**" security="none"/>
<http pattern="/resources/js/**" security="none"/>
<http use-expressions="false">
<intercept-url pattern="/**" access="ROLE_USER" />
<form-login />
<logout />
</http>

禁用CSRF防御

Spring Security默认启用CSRF防御,要求每个POST请求都要都要带上CSRF token参数,如果感觉比较麻烦或者网站安全性要求不高,可以配置禁用:

1
2
3
4
<http use-expressions="false">
...
<csrf disabled="true" />
</http>

获取登录用户信息

获取用户名:

1
2
httpServletRequest.getRemoteUser();  // Servlet标准,推荐使用
SecurityContextHolder.getContext().getAuthentication().getName();

获取用户ROLE:

1
SecurityContextHolder.getContext().getAuthentication().getAuthorities();

判断用户是否拥有ROLE:

1
httpServletRequest.isUserInRole("ADMIN");

Spring Security Web应用入门环境搭建的更多相关文章

  1. Spring MVC+Spring+Mybatis+MySQL(IDEA)入门框架搭建

    目录 Spring MVC+Spring+Mybatis+MySQL(IDEA)入门框架搭建 0.项目准备 1.数据持久层Mybatis+MySQL 1.1 MySQL数据准备 1.2 Mybatis ...

  2. ArcGIS API for Silverlight/ 开发入门 环境搭建

    Silverlight/ 开发入门 环境搭建1 Silverlight SDK下载ArcGIS API for Microsoft Silverlight/WPF ,需要注册一个ESRI Gloab ...

  3. spring-security-4 (2)spring security 基于Java配置的搭建

    一.spring security的模块 搭建spring security首先我们要导入必须的jar,即maven的依赖.spring security按模块划分,一个模块对应一个jar. spri ...

  4. Windows C#入门环境搭建

    Windows C#入门环境搭建 1. 安装Microsoft .NET Framework目录: C:\Windows\Microsoft.NET\Framework,查看已经安装的版本. 如果未安 ...

  5. Android开发使用控件入门--环境搭建

    Android开发使用控件入门--环境搭建 软件名称(,梦,,想.CAD  ,控件) 1. 环境搭建: 3 1.1. 安装Eclipse 3 1.2. 下载JDK 3 1.3. 下载Android S ...

  6. 57.NodeJS入门--环境搭建 IntelliJ IDEA

    转自:https://blog.csdn.net/wang19891106/article/details/51127133 NodeJS入门–环境搭建 IntelliJ IDEA 本人也刚开始学习N ...

  7. NodeJS入门--环境搭建 IntelliJ IDEA

    NodeJS入门–环境搭建 IntelliJ IDEA 本人也刚开始学习NodeJS,所以以此做个笔记,欢迎大家提出意见. 1.首先 下载安装NodeJS,下载安装IntelliJ IDEA 2.接下 ...

  8. Spring Security极简入门三部曲(上篇)

    目录 Spring Security极简入门三部曲(上篇) 写在前面 为什么要用Spring Security 数据库设计 demo时刻 核心代码讲解 小结 Spring Security极简入门三部 ...

  9. Spring Security极简入门三部曲(中篇)

    目录 Spring Security极简入门三部曲(中篇) 验证流程 Authentication接口 过滤器链 AuthenticationProvider接口: demo时刻 代码讲解 小结 Sp ...

随机推荐

  1. CF886F Symmetric Projections

    题意:给你平面上n个点,问有多少条过原点的直线,使得这些点在该直线上的投影(做垂直,对应点)形成对称图形?n<=2000. 标程: #include<bits/stdc++.h> # ...

  2. redis笔记_源码_字典dict

    参考:https://redissrc.readthedocs.io/en/latest/datastruct/dict.html Expand: 条件: 新的table 大小: Rehash: 条件 ...

  3. 【JZOJ6388】小w的作业

    description analysis 二分一个角度,首先假设该弧度角\(\theta \in[{\pi \over 2},\pi]\),要找的直线斜率\(k\in(-∞,\tan\theta]\) ...

  4. JS继承(简单理解版)

    童鞋们,我们今天聊聊js的继承,关于继承,平时开发基本用不到,但是面试没有不考的,我就想问,这是人干的事吗? 好吧,迫于社会主义核心价值观,我们今天就来简单说一说js的继承,谁让它是面向对象编程很重要 ...

  5. VS2010-MFC(文档、视图和框架:各对象之间的关系)

    转自:http://www.jizhuomi.com/software/223.html 前面一节进行了文档.视图和框架的概述,本节主要讲解文档.视图.框架结构中各对象之间的关系. 各个对象之间的关系 ...

  6. VS2010-MFC(对话框:消息对话框)

    转自:http://www.jizhuomi.com/software/171.html 前面几节讲了属性页对话框,我们可以根据所讲内容方便的建立自己的属性页对话框.本节讲解Windows系统中最常用 ...

  7. VUE的组件为什么要EXPORT DEFAULT 转载

    Vue的组件为什么要export default   Vue 的模块机制 Vue 是通过 webpack 实现的模块化,因此可以使用 import 来引入模块,例如: 此外,你还可以在 bulid/w ...

  8. this关键字、static关键字、block块、封装类以及继承、import、修饰符的初步了解

    this关键字 定义 在类的方法定义中使用this关键字代表使用该方法的引用. this即"自己",代表对象本身,谁调用代表谁.在成员方法中或构造器中隐式的传递. this的两种用 ...

  9. shell脚本练习02--求字符串的长度

    ######################################################################### # File Name: -.sh # Author ...

  10. DES加密算法-C语言

    头文件:DES.h #ifndef DES_hpp #define DES_hpp #include <stdio.h> #include <memory.h> #includ ...