鉴权模块springboot使用springsecurity
以前用spring整合security之后,因为自以为对springsecurity比较熟悉,所以一直没有好好总结过。现在的系统一般都会采用springboot来构建,所以现在打算来讲讲在springboot里面如何整合springsecurity。
前言
在伟大的spring时代,springsecurity就已经作为spring嫡系的鉴权框架,走进了广大程序员们的视野。相比于其他的鉴权框架来说,springsecuity的优势非常明显,功能强大且,鉴权力度较细,能和spring无缝接轨,几乎可以满足所有的业务需要,但它也有一些缺点,比如不易理解,当然,这是相对于同样在一些单点应用上是非流行的另一框架shero来说的。
然而,随着时代的进步,spring也在不断完善,直到今天,springboot的问世和流行,导致springsecurity的整合和理解也变得越来越简单,这主要还要归功于sopringboot开发人员做出的努力。在原有的springsecurity的基础上,springboot团队专门为其包装了springboot的起步依赖,使得springsercurity的整合难度急剧下降,即便是新手也能够很容易使用。
spring boot security 与spring security的关系
在spring security框架中,主要包含了两个依赖jar,分别是spring-security-web和spring-security-config依赖,分别如下:
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
spring boot对上面两个jar包进行了封装,仅仅只是封装,并没有改动spring security两个包的内容,并且加上了spring boot的起步依赖的特性,聚合成了spring-boot-starter-security这个起步依赖包,如下所示:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
整合步骤
上面说完了spring boot和spring security的关系后,简要的来叙述一下spring security的整合步骤。整个流程其实非常简单。
第一步:
构建一个spring boot工程,这个利用idea的Spring Initializr很容易就构建了
第二步:
引入spring boot为spring security的包装的起步依赖,也就是上面提到的spring-boot-starter-security,pom文件如下(整个pom文件都列出):
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
后端控制器代码:
package controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MainController {
@RequestMapping("/")
public String root(){
return "redirect:/index";
}
@RequestMapping("/index")
public String index(){
return "index";
}
@RequestMapping("/login")
public String login(){
return "login";
}
@RequestMapping("/user/index")
public String userIndex(){
return "/user/index";
}
@RequestMapping("/login-error")
public String loginError(Model model){
model.addAttribute("loginError",true);
return "login";
}
@RequestMapping("/401")
public String accessDenied(){
return "401";
}
}
后端的配置大致完成了,接下来为了演示清楚一些,编写一些简单的页面。
编写相关页面
我们使用了thymeleaf引擎,写一些html5页面,注意,thymeleaf也需要在application.yml进行配置。配置文件如下:
spring:
thymeleaf:
mode: HTML5
encoding: UTF-8
cache: false
登陆页面(login/html):
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>Login page</h1>
<p>User 角色用户:forezp/123456</p>
<p>Admin 角色用户:admin/123456</p>
<p th:if="${loginError}" class="error">用户名与密码错误</p>
<form th:action="@{/login}" method="post">
<label for="username">用户名</label>
<input type="text" id="username" name="username" autofocus="autofocus">
<br />
<label for="password"> 密码</label>
<input type="password" id="password" name="password">
<br />
<input type="submit" value="登录">
</form>
<p><a href="/index" th:href="@{/index}"> 返回首页</a></p>
</body>
</html>
首页(index.html):
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
<head>
<title>Hello spring security</title>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/css/main.css" th:href="@{/css/main.css}" />
</head>
<body>
<h1>Hello spring security</h1>
<p>这个界面没有受到保护,你可以进入已被保护的界面</p>
<div th:fragment="logout" sec:authorize="isAuthorize()">
登录用户:<span sec:authentication="name"></span> |
用户角色:<span sec:authentication="principal.authorities"></span>
<div>
<form action="#" th:action="@{/logout}" method="post">
<input type="submit" value="登出">
</form>
</div>
</div>
<ul>
<li>点击<a href="/user/index" th:href="@{/user/index}">去/user/index已被保护的界面</a></li>
</ul>
</body>
</html>
权限不够显示的页面(401.html):
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
<body>
<div>
<dev>
<h2>权限不够</h2>
</dev>
</div>
<div sec:authorize="isAuthenticated()">
<p>已有用户登录</p>
<p>用户:<span sec:authentication="name"></sapn></p>
<p>角色:<span sec:authentication="principal.authorities"></span></p>
</div>
<div sec:authentication="isAnonymous()">
<p>未有用户登录</p>
</div>
<p>
拒绝访问
</p>
</body>
</html>
用户首页(user/index.html),该资源被springsecurity保护,只拥有“USER”角色的用户才能够访问,其代码如下:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<title>Hello spring security</title>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/css/main.css" th:href="@{/css/main.css}"/>
</head>
<body>
<div th:substituteby="index::logout"></div>
<h1>这个是被保护的界面</h1>
<p><a href="/index" th:href="@{/index}">返回首页</a></p>
<p><a href="/index" th:href="@{/blogs}">管理博客</a></p>
</body>
</html>