Content Table

Spring Security 入门

目录结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
├── main
│   ├── java
│   │   └── com
│   │   └── xtuer
│   │   └── controller
│   │   └── HelloController.java
│   ├── resources
│   │   └── config
│   │   ├── spring-mvc.xml
│   │   └── spring-security.xml
│   └── webapp
│   └── WEB-INF
│   ├── view
│   │   └── fm
│   │   ├── admin.htm
│   │   └── hello.htm
│   └── web.xml
└── test
├── java
└── resources

Gradle 依赖

Spring Security + CAS 的依赖有:

  • spring-security-web
  • spring-security-config
  • spring-security-cas

注意: Spring Security 的版本和 Spring 的版本不是一样的

build.gradle

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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
group 'com.xtuer'
version '1.0'

apply plugin: 'java'
apply plugin: 'maven'
apply plugin: 'war'
apply plugin: 'org.akhikhl.gretty'

buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.akhikhl.gretty:gretty:1.4.0'
}
}

gretty {
port = 8081
contextPath = ''
servletContainer = 'tomcat7'

inplaceMode = 'hard'
debugSuspend = false
managedClassReload = true
recompileOnSourceChange = false
}

tasks.withType(JavaCompile) {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}

[compileJava, compileTestJava, javadoc]*.options*.encoding = 'UTF-8'

////////////////////////////////////////////////////////////////////////////////
// Maven 依赖 //
////////////////////////////////////////////////////////////////////////////////
repositories {
mavenLocal()
mavenCentral()
}

ext.versions = [
spring: '4.3.0.RELEASE',
springSecurity: '4.0.4.RELEASE',
servlet: '3.1.0',
fastjson: '1.2.17',
freemarker: '2.3.23',
junit: '4.12'
]

dependencies {
compile(
"org.springframework:spring-webmvc:$versions.spring", // Spring MVC
"org.springframework:spring-context-support:$versions.spring",
"org.springframework.security:spring-security-web:$versions.springSecurity", // Spring Security
"org.springframework.security:spring-security-config:$versions.springSecurity",
"org.springframework.security:spring-security-cas:$versions.springSecurity",
"com.alibaba:fastjson:$versions.fastjson", // JSON
"org.freemarker:freemarker:$versions.freemarker" // Freemarker
)

compileOnly("javax.servlet:javax.servlet-api:$versions.servlet")
testCompile("org.springframework:spring-test:$versions.spring")
testCompile("junit:junit:$versions.junit")
}

spring-security.xml

权限定义时为 ROLE_ADMIN,判断是否有权限时使用 hasRole('ADMIN')
需要多个权限: hasRole('ADMIN') and hasRole('DBA')

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version="1.0" encoding="UTF-8"?>
<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 auto-config="true">
<intercept-url pattern="/admin" access="hasRole('ADMIN')" />
</http>

<authentication-manager>
<authentication-provider>
<user-service>
<user name="admin" password="Passw0rd" authorities="ROLE_ADMIN"/>
<user name="alice" password="Passw0rd" authorities="ROLE_USER"/>
</user-service>
</authentication-provider>
</authentication-manager>
</beans:beans>

如果使用的是 Spring Security 5,则 password 加上前缀 {noop},为 password="{noop}Passw0rd",可参考 https://qtdebug.com/spring-security-4-encrypt

web.xml

Spring Security 是使用 Servlet Filter 来实现的,filter-name 必须为 springSecurityFilterChain

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
<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0"
metadata-complete="false">
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:config/spring-security.xml
</param-value>
</context-param>

<!-- Spring Security 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 MVC Servlet -->
<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:config/spring-mvc.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>

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
package com.xtuer.controller;

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.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class HelloController {
@RequestMapping("/")
@ResponseBody
public String index() {
return "index page";
}

@RequestMapping(value = {"/hello"}, method = RequestMethod.GET)
public String welcomePage(ModelMap model) {
model.addAttribute("title", "Spring Security Hello World");
model.addAttribute("message", "This is welcome page!");

return "hello.htm";
}

@RequestMapping(value = "/admin", method = RequestMethod.GET)
public String adminPage(ModelMap model) {
model.addAttribute("title", "Spring Security Hello World");
model.addAttribute("message", "This is protected page!");

UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
model.addAttribute("username", userDetails.getUsername());

return "admin.htm";
}
}

hello.htm

1
2
3
4
5
6
<html>
<body>
<h1>Title : ${title}</h1>
<h1>Message : ${message}</h1>
</body>
</html>

admin.htm

1
2
3
4
5
6
7
8
9
10
<html>
<body>
<h1>Title : ${title}</h1>
<h1>Message : ${message}</h1>

<#if username??>
<h2>Welcome : ${username}</h2>
</#if>
</body>
</html>

测试

参考