首先相信你已经按照上一篇的步骤搭好了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的错。
说明:
- intercept-url定义了一个权限控制的规则。
- user-service里面的3个user标签保存了用户信息在内存中。
- 使用user-service元素Spring Security底层使用的UserDetailsService就是InMemoryDaoImpl。InMemoryDaoImpl主要是测试用的,其只是简单地将用户信息保存在内存中。要从数据库加载UserDetails,则要使用JdbcDaoImpl。
- 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 | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> |
admin.jsp
1 | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> |
dba.jsp
1 | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> |
accessDenied.jsp
1 | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> |
小结
下一篇,连接数据库,从数据库加载UserDetails信息进行验证。