SpringSecurity学习(二)SpringSecurity框架搭建

首先相信你已经按照上一篇的步骤搭好了SpringMVC框架。这一篇要实现的是集成Spring Security框架,然后实现一个用户登录安全认证的例子。这个例子是参考国外一个大神的例子写的,他的博客里写到用xml配置和用java文件两种配置方法,非常牛X。英文原文地址http://websystique.com/spring-security/spring-security-4-hello-world-annotation-xml-example/

运行结果





项目结构

搭建步骤

添加依赖

集成Spring Security框架需要3个jar包。
在pom.xml的properties元素内添加一行代码:

1
<springsecurity.version>4.0.3.RELEASE</springsecurity.version>

Spring Security依赖的jar包:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!-- spring security -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>${springsecurity.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${springsecurity.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${springsecurity.version}</version>
</dependency>

说明:
如果项目报错了,那么在工程上右键——>Maven4MyEclipse——>Update Project…或者按快捷键Alt+F5,更新项目。

更新web.xml

为方便查看和修改springmvc-servlet.xml,也为方便集中管理配置文件,在src/main/resources目录下新建conf文件夹,把springmvc-servlet.xml复制到conf目录下,删除原来在WEB-INF目录下的springmvc-servlet.xml
web.xml文件内容如下:

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
29
30
31
32
33
34
35
36
37
38
39
40
41
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"

id="WebApp_ID" version="3.0">

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:conf/spring-security.xml;classpath:conf/springmvc-servlet.xml</param-value>
</context-param>

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

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:conf/springmvc-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>

Spring Security配置

spring-security.xml文件内容如下:

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
<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-4.1.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd">

<!-- use-expressions="true"启用表达式 -->
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/" access="permitAll" />
<intercept-url pattern="/home" access="permitAll" />
<intercept-url pattern="/admin**" access="hasRole('ADMIN')" />
<intercept-url pattern="/dba**"
access="hasRole('ADMIN') and hasRole('DBA')" />

<form-login authentication-failure-url="/Access_Denied" />
</http>

<authentication-manager>
<authentication-provider>
<user-service>
<user name="bill" password="abc123" authorities="ROLE_USER" />
<user name="admin" password="root123" authorities="ROLE_ADMIN" />
<user name="dba" password="root123" authorities="ROLE_ADMIN,ROLE_DBA" />
</user-service>
</authentication-provider>
</authentication-manager>

</beans:beans>

注:配置的时候一定要联网,否则会报找不到标签http和authentication-manager的错。
说明:

  1. intercept-url定义了一个权限控制的规则。
  2. user-service里面的3个user标签保存了用户信息在内存中。
  3. 使用user-service元素Spring Security底层使用的UserDetailsService就是InMemoryDaoImpl。InMemoryDaoImpl主要是测试用的,其只是简单地将用户信息保存在内存中。要从数据库加载UserDetails,则要使用JdbcDaoImpl。
  4. form-login元素是配置登录表单的,在第五篇中描述了如何自定义登录界面
    form-login元素有如下几个属性
    • login-page指定自定义的登录页面,不指定则使用Spring Security提供的默认登录页面。注:登录失败的页面要设置成在未登录的情况下可以访问
    • login-processing-url登录时提交的地址,默认是/j_spring-security-check。这个只是Spring Security用来标记登录页面使用的提交地址,真正关于登录这个请求是不需要用户自己处理的。
    • username-parameter登录时用户名使用的参数,默认值j_username,使用自定义登录页面要注意
    • password-parameter登录时密码使用的参数,默认值j_password,使用自定义登录页面要注意
    • default-target-url默认情况下,用户登录成功后会返回到原本受限制的页面。但用户直接请求登录页面,是跳转到当前应用的根路径。这个属性指定用户在直接访问登录页面并成功登录后跳转到的页面。
    • always-use-default-target设为true,表示无论是直接访问登录页面,还是在访问受限页面跳转到了登录页面,登录成功后都是跳转到default-target-url指定的页面。
    • anthentication-failure-url默认情况下登录失败会返回登录页面,此属性指定登录失败后跳转到的页面。注:登录失败的页面要设置成在未登录的情况下可以访问
    • authentication-success-handler-ref
    • authentication-failure-handler-ref

修改HelloController

HelloController类:

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
@Controller
public class HelloController {

@RequestMapping(value = { "/", "/home" }, method = RequestMethod.GET)
public String homePage(Model model) {
model.addAttribute("greeting", "Hi, Welcome to mysite. ");
return "welcome";
}

@RequestMapping(value = "/admin", method = RequestMethod.GET)
public String adminPage(ModelMap model) {
model.addAttribute("user", getPrincipal());
return "admin";
}

@RequestMapping(value = "/dba", method = RequestMethod.GET)
public String dbaPage(ModelMap model) {
model.addAttribute("user", getPrincipal());
return "dba";
}

@RequestMapping(value="/logout", method = RequestMethod.GET)
public String logoutPage (HttpServletRequest request, HttpServletResponse response) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null){
new SecurityContextLogoutHandler().logout(request, response, auth);
}
return "welcome";
}

@RequestMapping(value = "/Access_Denied", method = RequestMethod.GET)
public String accessDeniedPage(ModelMap model) {
model.addAttribute("user", getPrincipal());
return "accessDenied";
}

private String getPrincipal(){
String userName = null;
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();

if (principal instanceof UserDetails) {
userName = ((UserDetails)principal).getUsername();
} else {
userName = principal.toString();
}
return userName;
}
}

4个视图

welcome.jsp

1
2
3
4
5
6
7
8
9
10
11
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>HelloWorld page</title>
</head>
<body>
Greeting : ${greeting}
This is a welcome page.
</body>
</html>

admin.jsp

1
2
3
4
5
6
7
8
9
10
11
12
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>HelloWorld Admin page</title>
</head>
<body>
Dear <strong>${user}</strong>, Welcome to Admin Page.
<a href="<c:url value="/logout" />">Logout</a>
</body>
</html>

dba.jsp

1
2
3
4
5
6
7
8
9
10
11
12
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>DBA page</title>
</head>
<body>
Dear <strong>${user}</strong>, Welcome to DBA Page.
<a href="<c:url value="/logout" />">Logout</a>
</body>
</html>

accessDenied.jsp

1
2
3
4
5
6
7
8
9
10
11
12
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>AccessDenied page</title>
</head>
<body>
Dear <strong>${user}</strong>, You are not authorized to access this page
<a href="<c:url value="/logout" />">Logout</a>
</body>
</html>

小结

下一篇,连接数据库,从数据库加载UserDetails信息进行验证。

热评文章