springboot2 安全配置
1. 结构
1.1 导包
版本对应: thymeleaf3 - - - layout2 - - - security3
springboot2 默认 thymeleaf-extras-springsecurity5 是3
版本
<properties>
<java.version>1.8</java.version>
<!-- thymeleaf3 版本 对应 layout2 版本 -->
<thymeleaf.version>3.0.11.RELEASE</thymeleaf.version>
<thymeleaf-layout-dialect.version>2.4.1</thymeleaf-layout-dialect.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-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
1.2 前台页面
只显示 index.html 和 userLogin.html 其它页简单
1.2.1 index.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="keywords" content="maven, index"/>
<title>index</title>
<link rel="stylesheet" type="text/css" th:href="@{/css/bootstrap.min.css}"/>
</head>
<body>
<div class="container">
<h1>首页</h1>
<br/>
<div sec:authorize="!isAuthenticated()">
<h4>游客你好! <a th:href="@{/user_login}">登录</a></h4>
</div>
<div sec:authorize="isAuthenticated()">
<h4>
<span sec:authentication="name"></span> 您好! 您的角色有: <span sec:authentication="principal.authorities"></span>
</h4>
<form th:action="@{/logout}" method="post">
<input class="btn" type="submit" value="LOGOUT">
</form>
</div>
<br/>
<h2>0</h2>
<a th:href="@{/vip_0/1}">Ordinary users1</a><br/>
<a th:href="@{/vip_0/2}">Ordinary users2</a><br/>
<a th:href="@{/vip_0/3}">Ordinary users3</a><br/>
<div sec:authorize="hasRole('VIP')">
<h2>VIP</h2>
<a th:href="@{/vip_1/1}">VIP user1</a><br/>
<a th:href="@{/vip_1/2}">VIP user2</a><br/>
<a th:href="@{/vip_1/3}">VIP user3</a><br/>
</div>
<div sec:authorize="hasRole('mVip')">
<h2>MVIP</h2>
<a th:href="@{/mVip/1}">MVIP user1</a><br/>
<a th:href="@{/mVip/2}">MVIP user2</a><br/>
<a th:href="@{/mVip/3}">MVIP user3</a><br/>
</div>
</div>
<script th:src="@{/js/jquery-3.3.1.min.js}" type="text/javascript" charset="utf-8"></script>
</body>
</html>
1.2.2 userLogin.html
定制登入页面
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="keywords" content="maven, index"/>
<title>index</title>
<link rel="stylesheet" type="text/css" th:href="@{/css/bootstrap.min.css}"/>
</head>
<body>
<div class="container">
<div class="text-center">
<h1>欢迎来到这里查看安全权力</h1>
</div>
<hr/>
<div class="row">
<div class="col-4"></div>
<div class="col-4">
<form method="post" th:action="@{/user_login}">
<p>
<label for="user"> Username
<input type="text" id="user" name="user" class="form-control" placeholder="Username">
</label>
</p>
<p>
<label for="password"> Password
<input type="password" id="password" name="password" class="form-control" placeholder="Password">
</label>
</p>
<p>
<label for="remember">
<input id="remember" type="checkbox" name="remember"> Remember me on this computer.
</label>
</p>
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
</form>
</div>
<div class="col-4"></div>
</div>
</div>
</body>
</html>
1.3 controller 层
IndexController.java
package com.ykenan.ykenan.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class IndexController {
@GetMapping("/index")
public String index() {
return "index";
}
@GetMapping("/user_login")
public String user_login() {
return "userLogin";
}
@GetMapping("/mVip/1")
public String mVip1() {
return "mVip1";
}
@GetMapping("/mVip/2")
public String mVip2() {
return "mVip2";
}
@GetMapping("/mVip/3")
public String mVip3() {
return "mVip3";
}
@GetMapping("/vip_0/1")
public String vip01() {
return "vip01";
}
@GetMapping("/vip_0/2")
public String vip02() {
return "vip02";
}
@GetMapping("/vip_0/3")
public String vip03() {
return "vip03";
}
@GetMapping("/vip_1/1")
public String vip11() {
return "vip11";
}
@GetMapping("/vip_1/2")
public String vip12() {
return "vip12";
}
@GetMapping("/vip_1/3")
public String vip13() {
return "vip13";
}
}
1.4 安全配置
认证, 授权, 权限控制, 注销, 网页记住
package com.ykenan.ykenan.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
/**
* EnableWebSecurity: Introducing Security Configuration Permissions.
*/
@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
/**
* Define authorization rules.
* @param http http
* @throws Exception Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
//super.configure(http);
/* Setting Path Access Permissions. */
http.authorizeRequests().mvcMatchers("/index", "/vip_0/**")
.permitAll()
.mvcMatchers("/vip_1/**").hasAnyRole("VIP")
.mvcMatchers("/mVip/**").hasAnyRole("mVip");
/* Turn on automatic configuration function. */
http.formLogin().usernameParameter("user").passwordParameter("password").loginPage("/user_login");
/* Turn on remember me function. */
http.rememberMe().rememberMeParameter("remember");
/* Turn on logout function. */
http.logout().logoutSuccessUrl("/");
}
/**
* Define authorization rules.
* @param auth auth
* @throws Exception Exception
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//super.configure(auth);
auth.inMemoryAuthentication().passwordEncoder(passwordEncoder())
.withUser("user_VIP").password(passwordEncoder().encode("123456")).roles("VIP")
.and()
.withUser("user_MVIP").password(passwordEncoder().encode("456789")).roles("VIP", "mVip");
}
/**
* Support multiple encoding, distinguish encoding methods by prefix of password.
* @return PasswordEncoder
*/
@Bean
PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
}
2. 添加(option)
若项目中用到了
druid
, 会对其进行csrf
校验, 报403
错误.
需要加上下面这个
/* Checking CSRF of Druid with security ignored. */
http.csrf().ignoringAntMatchers("/druid/*");