本文仅介绍Spring Security的基本使用。
Spring Security 基于 Spring 框架,提供了一套 Web 应用安全性的完整解决方案。Web 应用的安全性包括用户认证(Authentication)和用户授权(Authorization)两个部分。
身份验证技术主要有:
身份验证 | . . . |
---|---|
HTTP BASIC |
单点登陆 |
HTTP Digest |
Remember-Me |
HTTP X.509 |
匿名身份验证 |
LDAP |
Run-as |
基于表单的认证 | JAAS |
OpenID |
JavaEE 容器认证 |
完整工程
关键代码:
dependencies {
//SpringBoot必要组件和测试组件
implementation('org.springframework.boot:spring-boot-starter-web')
testImplementation('org.springframework.boot:spring-boot-starter-test')
//thymeleaf 模板引擎
compile('org.springframework.boot:spring-boot-starter-thymeleaf')
//Spring Data JPA 持久层支持
compile('org.springframework.boot:spring-boot-starter-data-jpa')
//Mysql 连接驱动
compile('mysql:mysql-connector-java:8.0.11')
//H2 内存数据库
runtime('com.h2database:h2:1.4.193')
//Spring Security 权限管理
compile('org.springframework.boot:spring-boot-starter-security')
//Thymeleaf Spring Security 对Thymeleaf的支持
compile('org.thymeleaf.extras:thymeleaf-extras-springsecurity4:3.0.2.RELEASE')
}
完整代码:HERE
SecurityConfig.java为配置类,继承自org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
类。
用于自定义一些配置。
package com.example.demo.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
/**
* 自定义权限配置
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/css/**", "/js/**", "/fonts/**", "/index").permitAll()// 都可以访问
.antMatchers("/users/**").hasRole("ADMIN")// 需要相应角色权限才能访问
.and().formLogin()// 基于Form表单验证
.loginPage("/login").failureUrl("/login-error");// 自定义登陆界面
http.csrf().disable();// 禁用security的csrf功能
}
/**
* 用户认证
* 添加用户名为admin密码为12345的ADMIN权限用户
* @param auth
* @throws Exception
*/
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()// 认证信息储存在内存中
.withUser("admin").password("12345").roles("ADMIN");
}
}
这里注意:
http.csrf().disable();// 禁用security的csrf功能
这句是为了使RESTful
正常使用。
这里设定了/css/**
、/js/**
、/fonts/**
、/index
是都可以访问且不涉及权限的,但需要ADMIN
账户才能访问。且登陆基于Form
表单验证,登陆界面和登陆错误返回页面分别为/login
、/login-error
。
并将账号信息注入到内存中,即用户名为admin
密码为12345
的ADMIN
权限用户,此例未将账号信息存储到持久层内。
@Controller
public class MainController {
@GetMapping("/")
public String root() {
return "redirect:/index";
}
@GetMapping("/index")
public String index() {
return "index";
}
@GetMapping("/login")
public String login() {
return "login";
}
@GetMapping("/login-error")
public String loginError(Model model) {
model.addAttribute("loginError",true);
model.addAttribute("errorMsg", "登陆失败,用户名或密码错误!");
return "login";
}
}
完整代码:HERE
header.html
会根据用户是否登陆显示不同的内容。
<div sec:authorize="isAuthenticated()" class="row">
<ul class="nav navbar-nav navbar-right">
<li><a><span class="nav-link" sec:authentication="name">span>a>li>
<li><a href="javascript:doPost()" class="btn btn-outline-success">退出<span class="sr-only">(current)span>a>li>
ul>
div>
<div sec:authorize="isAnonymous()">
<ul class="nav navbar-nav navbar-right">
<li><a href="/login" th:href="@{~/login}" class="btn btn-outline-success">登陆a>li>
ul>
div>
footer.html
将javascript:doPost()
函数也根据用户是否登陆显示出来。
<div sec:authorize="isAuthenticated()">
<script>
function doPost() { // 登出函数
var myForm = document.createElement("form");
myForm.method = "post";
myForm.action = "/logout";
document.body.appendChild(myForm);
myForm.submit();
document.body.removeChild(myForm); // 提交后移除创建的form
}
script>
div>
此处用JavaScript创建一个表单,要想正常工作须在前面配置文件初加上代码:
http.csrf().disable();// 禁用security的csrf功能
来禁用security的csrf功能。
index.html
根据用户是否登陆显示不同的页面。
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
<head th:replace="~{fragments/header::header}">
head>
<body>
<div class="container">
<div class="jumbotron">
<div sec:authorize="isAuthenticated()">
<p>已有用户登陆p>
<p>
登陆的用户为:<span sec:authentication="name">span>
p>
<p>
用户角色为:<span sec:authentication="principal.authorities">span>
p>
div>
<div sec:authorize="isAnonymous()">
<p>未有用户登陆p>
div>
div>
div>
<div th:replace="~{fragments/footer::footer}">div>
body>
html>
login.html
则是根据一个form
表单来提交账号密码。
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
<head th:replace="~{fragments/header::header}">
head>
<body>
<div class="container">
<div class="jumbotron">
<form th:action="@{~/login}" method="post">
<h2>请登录h2>
<div class="form-group col-md-5">
<label for="username" class="col-form-label">账号label> <input
type="text" class="form-control" id="username" name="username"
maxlength="50" placeholder="请输入账号">
div>
<div class="form-group col-md-5">
<label for="password" class="col-form-label">密码label> <input
type="password" class="form-control" id="password" name="password"
maxlength="30" placeholder="请输入密码">
div>
<div class="form-group col-md-5">
<button type="submit" class="btn btn-primary">登陆button>
div>
<div class="col-md-5" th:if="${loginError}">
<p class="label-error" th:text="${errorMsg}">p>
div>
form>
<br><br><br><br><br><br>
div>
div>
<div th:replace="~{fragments/footer::footer}">div>
body>
html>
完成后界面:
完整项目地址:HRER