1 設置登錄的用戶名和密碼
1.1 通過配置文件
- application.properties
server.port=8181
# 設置登錄的用戶名和密碼
spring.security.user.name=admin
spring.security.user.password=123456
1.2 通過配置類
- SpringSecurityConfig.java
package com.sunxiaping.springsecurity.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.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
/**
* SpringSecurity的配置類
*
* @author 許大仙
* @version 1.0
* @since 2020-10-28 13:38
*/
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String password = passwordEncoder.encode("123456");
auth.inMemoryAuthentication().withUser("admin").password(password).roles("ADMIN");
}
}
1.3 自定義編寫UserDetailsService實現類
- UserDetailsServiceImpl.java
package com.sunxiaping.springsecurity.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @author 許大仙
* @version 1.0
* @since 2020-10-28 13:57
*/
@Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
if (!"admin".equals(username)) {
throw new UsernameNotFoundException("用戶不存在");
}
String password = passwordEncoder.encode("123456");
Collection<? extends GrantedAuthority> authorities = Stream.of(new SimpleGrantedAuthority("ADMIN")).collect(Collectors.toList());
UserDetails userDetails = new User(username, password, authorities);
return userDetails;
}
}
- SpringSecurityConfig.java
package com.sunxiaping.springsecurity.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
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.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import javax.naming.Name;
/**
* SpringSecurity的配置類
*
* @author 許大仙
* @version 1.0
* @since 2020-10-28 13:38
*/
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier(value = "userDetailsService")
private UserDetailsService userDetailsService;
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}
}
2 查詢數據庫完成認證
2.1 導入JPA等相關jar包的Maven坐標
- 修改部分:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
- 完整部分:
<?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 https://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.2.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.sunxiaping</groupId>
<artifactId>spring-security</artifactId>
<version>1.0</version>
<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-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-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>
2.2 sql腳本
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for users
-- ----------------------------
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = MyISAM AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
insert into (id,username,password) users values(1,'admin','$2a$10$Ug6eGqhTX7wY8ZVIe2PbC.ljVWEko5h7ZH92N.rg0ZjZBcgg2VOqm');
2.3 修改配置文件
- application.properties
server.port=8181
# 數據庫連接配置信息
spring.datasource.url=jdbc:mysql://192.168.1.57:3306/test?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=root
# JPA相關配置
spring.jpa.show-sql=true
spring.jpa.database=mysql
spring.jpa.hibernate.ddl-auto=update
spring.jpa.open-in-view=true
2.4 編寫實體類
- Users.java
package com.sunxiaping.springsecurity.domain;
import lombok.*;
import javax.persistence.*;
import java.io.Serializable;
/**
* @author 許大仙
* @version 1.0
* @since 2020-10-28 14:37
*/
@Table(name = "users")
@Entity
@Setter
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Users implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
}
2.5 編寫UsersRepository接口
package com.sunxiaping.springsecurity.dao;
import com.sunxiaping.springsecurity.domain.Users;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
/**
* @author 許大仙
* @version 1.0
* @since 2020-10-28 14:43
*/
public interface UsersRepository extends JpaRepository<Users, Long>, JpaSpecificationExecutor<Users> {
}
2.6 編寫UserDetailsService的實現類
package com.sunxiaping.springsecurity.service;
import com.sunxiaping.springsecurity.dao.UsersRepository;
import com.sunxiaping.springsecurity.domain.Users;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @author 許大仙
* @version 1.0
* @since 2020-10-28 13:57
*/
@Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UsersRepository usersRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Optional<Users> optional = usersRepository.findOne(Example.of(Users.builder().username(username).build()));
Users users = optional.orElseThrow(() -> new UsernameNotFoundException("用戶不存在"));
Collection<? extends GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList("ADMIN");
UserDetails userDetails = new User(username, users.getPassword(), authorities);
return userDetails;
}
}
2.7 編寫SpringSecurity的配置類
package com.sunxiaping.springsecurity.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
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.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
/**
* SpringSecurity的配置類
*
* @author 許大仙
* @version 1.0
* @since 2020-10-28 13:38
*/
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier(value = "userDetailsService")
private UserDetailsService userDetailsService;
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}
}
2.8 啟動類
package com.sunxiaping.springsecurity;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication
@EnableJpaAuditing
@EnableTransactionManagement
public class SpringSecurityApplication {
public static void main(String[] args) {
SpringApplication.run(SpringSecurityApplication.class, args);
}
}
3 未認證請求跳轉到登錄頁面
3.1 導入thymeleaf相關jar包的Maven坐標
- 修改部分:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
- 完整部分:
<?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 https://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.2.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.sunxiaping</groupId>
<artifactId>spring-security</artifactId>
<version>1.0</version>
<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-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3.2 編寫WebMvcConfig
package com.sunxiaping.springsecurity.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @author 許大仙
* @version 1.0
* @since 2020-10-28 16:07
*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login.html").setViewName("login");
registry.addViewController("/").setViewName("login");
// registry.addViewController("/login").setViewName("login");
// registry.addViewController("/index").setViewName("login");
registry.addViewController("/success").setViewName("success");
registry.addViewController("/failure").setViewName("failure");
}
}
3.3 在templates目錄下新建login.html、success.html和failure.html
- login.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>登錄頁面</title>
</head>
<body>
<form th:action="@{/login}" method="post">
用戶名: <input type="text" name="username"><br>
密碼:<input type="password" name="password"> <br>
<input type="submit" value="登錄">
</form>
</body>
</html>
- success.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
登錄成功
</body>
</html>
- failure.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
登錄失敗
</body>
</html>
3.4 修改SpringSecurityConfig
package com.sunxiaping.springsecurity.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
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.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
/**
* SpringSecurity的配置類
*
* @author 許大仙
* @version 1.0
* @since 2020-10-28 13:38
*/
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier(value = "userDetailsService")
private UserDetailsService userDetailsService;
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin() //自定義自己編寫的登錄頁面
.loginPage("/login.html") //登錄頁面設置
.usernameParameter("username")
.passwordParameter("password")
.loginProcessingUrl("/login")//登錄訪問的路徑
.defaultSuccessUrl("/success") //登錄成功,跳轉的路徑
.failureUrl("/failure")
.permitAll() //指定路徑,無需保護
.and()
.authorizeRequests()
.antMatchers("/", "/login", "/test/hello")
.permitAll()
.anyRequest() //其他路徑,需要認證
.authenticated()
.and().csrf().disable();//關閉CSRF
}
}
4 基於角色或權限進行訪問控制
4.1 hasAuthority()方法
-
如果當前的主體具有指定的權限,則返回true,否則返回false。
-
修改SpringSecurityConfig.java
package com.sunxiaping.springsecurity.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
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.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
/**
* SpringSecurity的配置類
*
* @author 許大仙
* @version 1.0
* @since 2020-10-28 13:38
*/
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier(value = "userDetailsService")
private UserDetailsService userDetailsService;
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin() //自定義自己編寫的登錄頁面
.loginPage("/login.html") //登錄頁面設置
.usernameParameter("username")
.passwordParameter("password")
.loginProcessingUrl("/login")//登錄訪問的路徑
.defaultSuccessUrl("/success") //登錄成功,跳轉的路徑
.failureUrl("/failure")
.permitAll() //指定路徑,無需保護
.and()
.authorizeRequests()
.antMatchers("/", "/login", "/test/hello").permitAll()
//-----------設置權限admins------------
.antMatchers("/test/hello").hasAuthority("admins")
.anyRequest() //其他路徑,需要認證
.authenticated()
.and().csrf().disable();//關閉CSRF
}
}
- 修改UserDetailsServiceImpl.java
package com.sunxiaping.springsecurity.service;
import com.sunxiaping.springsecurity.dao.UsersRepository;
import com.sunxiaping.springsecurity.domain.Users;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.Optional;
/**
* @author 許大仙
* @version 1.0
* @since 2020-10-28 13:57
*/
@Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UsersRepository usersRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Optional<Users> optional = usersRepository.findOne(Example.of(Users.builder().username(username).build()));
Users users = optional.orElseThrow(() -> new UsernameNotFoundException("用戶不存在"));
//這邊的admins要和SpringSecurityConfig中.antMatchers("/test/hello").hasAuthority("admins")中的admins一致
Collection<? extends GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList("admins");
UserDetails userDetails = new User(username, users.getPassword(), authorities);
return userDetails;
}
}
4.2 hasAnyAuthority方法
-
如果當前的主體具有很多指定的權限的話,返回true。
-
修改SpringSecurityConfig.java
package com.sunxiaping.springsecurity.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
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.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
/**
* SpringSecurity的配置類
*
* @author 許大仙
* @version 1.0
* @since 2020-10-28 13:38
*/
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier(value = "userDetailsService")
private UserDetailsService userDetailsService;
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin() //自定義自己編寫的登錄頁面
.loginPage("/login.html") //登錄頁面設置
.usernameParameter("username")
.passwordParameter("password")
.loginProcessingUrl("/login")//登錄訪問的路徑
.defaultSuccessUrl("/success") //登錄成功,跳轉的路徑
.failureUrl("/failure")
.permitAll() //指定路徑,無需保護
.and()
.authorizeRequests()
.antMatchers("/", "/login", "/test/hello").permitAll()
//-----------設置權限admins,hellos------------
.antMatchers("/test/hello").hasAnyAuthority("admins", "hellos")
.anyRequest() //其他路徑,需要認證
.authenticated()
.and().csrf().disable();//關閉CSRF
}
}
- 修改UserDetailsServiceImpl.java
package com.sunxiaping.springsecurity.service;
import com.sunxiaping.springsecurity.dao.UsersRepository;
import com.sunxiaping.springsecurity.domain.Users;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.Optional;
/**
* @author 許大仙
* @version 1.0
* @since 2020-10-28 13:57
*/
@Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UsersRepository usersRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Optional<Users> optional = usersRepository.findOne(Example.of(Users.builder().username(username).build()));
Users users = optional.orElseThrow(() -> new UsernameNotFoundException("用戶不存在"));
//這邊的admin和hellos要和SpringSecurityConfig中.antMatchers("/test/hello").hasAnyAuthority("admins", "hellos")中的admins和hellos一致
Collection<? extends GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList("admins,hellos");
UserDetails userDetails = new User(username, users.getPassword(), authorities);
return userDetails;
}
}
4.3 hasRole方法
-
如果用戶具備給定角色就允許訪問,否則出現403。
-
修改SpringSecurityConfig.java
package com.sunxiaping.springsecurity.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
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.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
/**
* SpringSecurity的配置類
*
* @author 許大仙
* @version 1.0
* @since 2020-10-28 13:38
*/
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier(value = "userDetailsService")
private UserDetailsService userDetailsService;
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin() //自定義自己編寫的登錄頁面
.loginPage("/login.html") //登錄頁面設置
.usernameParameter("username")
.passwordParameter("password")
.loginProcessingUrl("/login")//登錄訪問的路徑
.defaultSuccessUrl("/success") //登錄成功,跳轉的路徑
.failureUrl("/failure")
.permitAll() //指定路徑,無需保護
.and()
.authorizeRequests()
.antMatchers("/", "/login", "/test/hello").permitAll()
//-----------設置角色為ADMIN,那么數據庫中對應的角色必須為ROLE_ADMIN------------
.antMatchers("/test/hello").hasRole("ADMIN")
.anyRequest() //其他路徑,需要認證
.authenticated()
.and().csrf().disable();//關閉CSRF
}
}
- 修改UserDetailsServiceImpl.java
package com.sunxiaping.springsecurity.service;
import com.sunxiaping.springsecurity.dao.UsersRepository;
import com.sunxiaping.springsecurity.domain.Users;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.Optional;
/**
* @author 許大仙
* @version 1.0
* @since 2020-10-28 13:57
*/
@Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UsersRepository usersRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Optional<Users> optional = usersRepository.findOne(Example.of(Users.builder().username(username).build()));
Users users = optional.orElseThrow(() -> new UsernameNotFoundException("用戶不存在"));
Collection<? extends GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_ADMIN");
UserDetails userDetails = new User(username, users.getPassword(), authorities);
return userDetails;
}
}
4.4 hasAnyRole方法
-
表示用戶具備任何一個角色都可以訪問。
-
修改SpringSecurityConfig.java
package com.sunxiaping.springsecurity.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
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.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
/**
* SpringSecurity的配置類
*
* @author 許大仙
* @version 1.0
* @since 2020-10-28 13:38
*/
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier(value = "userDetailsService")
private UserDetailsService userDetailsService;
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin() //自定義自己編寫的登錄頁面
.loginPage("/login.html") //登錄頁面設置
.usernameParameter("username")
.passwordParameter("password")
.loginProcessingUrl("/login")//登錄訪問的路徑
.defaultSuccessUrl("/success") //登錄成功,跳轉的路徑
.failureUrl("/failure")
.permitAll() //指定路徑,無需保護
.and()
.authorizeRequests()
.antMatchers("/", "/login", "/test/hello").permitAll()
//-----------設置角色為ADMIN,那么數據庫中對應的角色必須為ROLE_ADMIN------------
.antMatchers("/test/hello").hasAnyRole("ADMIN", "TEST")
.anyRequest() //其他路徑,需要認證
.authenticated()
.and().csrf().disable();//關閉CSRF
}
}
- 修改UserDetailsServiceImpl.java
package com.sunxiaping.springsecurity.service;
import com.sunxiaping.springsecurity.dao.UsersRepository;
import com.sunxiaping.springsecurity.domain.Users;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.Optional;
/**
* @author 許大仙
* @version 1.0
* @since 2020-10-28 13:57
*/
@Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UsersRepository usersRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Optional<Users> optional = usersRepository.findOne(Example.of(Users.builder().username(username).build()));
Users users = optional.orElseThrow(() -> new UsernameNotFoundException("用戶不存在"));
Collection<? extends GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_ADMIN,ROLE_TEST");
UserDetails userDetails = new User(username, users.getPassword(), authorities);
return userDetails;
}
}
5 自定義403頁面
- 修改訪問配置類:
package com.sunxiaping.springsecurity.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
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.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
/**
* SpringSecurity的配置類
*
* @author 許大仙
* @version 1.0
* @since 2020-10-28 13:38
*/
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier(value = "userDetailsService")
private UserDetailsService userDetailsService;
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
//自定義403頁面
http.exceptionHandling().accessDeniedPage("/403");
http.formLogin() //自定義自己編寫的登錄頁面
.loginPage("/login.html") //登錄頁面設置
.usernameParameter("username")
.passwordParameter("password")
.loginProcessingUrl("/login")//登錄訪問的路徑
.defaultSuccessUrl("/success") //登錄成功,跳轉的路徑
.failureUrl("/failure")
.permitAll() //指定路徑,無需保護
.and()
.authorizeRequests()
.antMatchers("/", "/login", "/test/hello").permitAll()
//-----------設置角色為ADMIN,那么數據庫中對應的角色必須為ROLE_ADMIN------------
.antMatchers("/test/hello").hasAnyRole("ADMIN", "TEST")
.anyRequest() //其他路徑,需要認證
.authenticated()
.and().csrf().disable();//關閉CSRF
}
}
- 在templates目錄下新建error目錄,並新建4xx.html文件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>403</title>
</head>
<body>
對不起,你沒有權限訪問。
</body>
</html>
6 使用注解進行用戶授權
6.1 前提
- 在啟動類或配置類中開啟全局方法級別的安全控制:
package com.sunxiaping.springsecurity;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication
@EnableJpaAuditing
@EnableTransactionManagement
//開啟全局方法級別的安全控制
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class SpringSecurityApplication {
public static void main(String[] args) {
SpringApplication.run(SpringSecurityApplication.class, args);
}
}
6.2 @Secured注解
-
此注解用於判斷是否具有某個角色,需要注意的是,匹配的字符串前面需要添加“ROLE_”。
-
示例:
package com.sunxiaping.springsecurity.controller;
import org.springframework.security.access.annotation.Secured;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author 許大仙
* @version 1.0
* @since 2020-10-28 16:16
*/
@RestController
public class TestController {
@Secured({"ROLE_SALE","ROLE_ADMIN"})
@GetMapping(value = "/test/hello")
public String hello(){
return "test/hello";
}
}
package com.sunxiaping.springsecurity.service;
import com.sunxiaping.springsecurity.dao.UsersRepository;
import com.sunxiaping.springsecurity.domain.Users;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.Optional;
/**
* @author 許大仙
* @version 1.0
* @since 2020-10-28 13:57
*/
@Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UsersRepository usersRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Optional<Users> optional = usersRepository.findOne(Example.of(Users.builder().username(username).build()));
Users users = optional.orElseThrow(() -> new UsernameNotFoundException("用戶不存在"));
//AuthorityUtils的commaSeparatedStringToAuthorityList方法的入參需要和@Secured中的一致,否則會報錯,當然實際項目中是從數據庫中查詢得到的
Collection<? extends GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_SALE,ROLE_ADMIN");
UserDetails userDetails = new User(username, users.getPassword(), authorities);
return userDetails;
}
}
6.2 @PreAuthorize注解
-
@PreAuthorize注解適合進入方法前的權限驗證。
-
示例:
package com.sunxiaping.springsecurity.controller;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author 許大仙
* @version 1.0
* @since 2020-10-28 16:16
*/
@RestController
public class TestController {
@PreAuthorize("hasAnyAuthority('sys:test','sys:add')")
@GetMapping(value = "/test/hello")
public String hello(){
return "test/hello";
}
}
package com.sunxiaping.springsecurity.service;
import com.sunxiaping.springsecurity.dao.UsersRepository;
import com.sunxiaping.springsecurity.domain.Users;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.Optional;
/**
* @author 許大仙
* @version 1.0
* @since 2020-10-28 13:57
*/
@Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UsersRepository usersRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Optional<Users> optional = usersRepository.findOne(Example.of(Users.builder().username(username).build()));
Users users = optional.orElseThrow(() -> new UsernameNotFoundException("用戶不存在"));
//AuthorityUtils的commaSeparatedStringToAuthorityList方法的入參需要和@PreAuthorize中的一致,否則會報錯,當然實際項目中是從數據庫中查詢得到的
Collection<? extends GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList("sys:test,sys:add");
UserDetails userDetails = new User(username, users.getPassword(), authorities);
return userDetails;
}
}
6.3 @PostAuthorize注解
-
@PostAuthorize注解使用的不多,在方法執行后再進行權限校驗,適合驗證帶有返回值的權限。
-
示例:
package com.sunxiaping.springsecurity.controller;
import org.springframework.security.access.prepost.PostAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author 許大仙
* @version 1.0
* @since 2020-10-28 16:16
*/
@RestController
public class TestController {
@PostAuthorize("hasAnyAuthority('sys:test','sys:add')")
@GetMapping(value = "/test/hello")
public String hello(){
return "test/hello";
}
}
package com.sunxiaping.springsecurity.service;
import com.sunxiaping.springsecurity.dao.UsersRepository;
import com.sunxiaping.springsecurity.domain.Users;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.Optional;
/**
* @author 許大仙
* @version 1.0
* @since 2020-10-28 13:57
*/
@Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UsersRepository usersRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Optional<Users> optional = usersRepository.findOne(Example.of(Users.builder().username(username).build()));
Users users = optional.orElseThrow(() -> new UsernameNotFoundException("用戶不存在"));
//AuthorityUtils的commaSeparatedStringToAuthorityList方法的入參需要和@PostAuthorize中的一致,否則會報錯,當然實際項目中是從數據庫中查詢得到的
Collection<? extends GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList("sys:test,sys:add");
UserDetails userDetails = new User(username, users.getPassword(), authorities);
return userDetails;
}
}
7 用戶注銷
7.1 在配置類中添加退出的映射地址
- SpringSecurityConfig的修改部分:
//添加退出的映射地址
http.logout().logoutUrl("/logout").logoutSuccessUrl("/login").permitAll();
- SpringSecurityConfig的完整部分:
package com.sunxiaping.springsecurity.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
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.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
/**
* SpringSecurity的配置類
*
* @author 許大仙
* @version 1.0
* @since 2020-10-28 13:38
*/
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier(value = "userDetailsService")
private UserDetailsService userDetailsService;
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
//配置沒有權限訪問跳轉自定義頁面
http.exceptionHandling().accessDeniedPage("/403.html");
//添加退出的映射地址
http.logout().logoutUrl("/logout").logoutSuccessUrl("/login").permitAll();
http.formLogin() //自定義自己編寫的登錄頁面
.loginPage("/login.html") //登錄頁面設置
.usernameParameter("username")
.passwordParameter("password")
.loginProcessingUrl("/login")//登錄訪問的路徑
.defaultSuccessUrl("/success") //登錄成功,跳轉的路徑
.failureUrl("/failure")
.permitAll() //指定路徑,無需保護
.and()
.authorizeRequests()
.antMatchers("/", "/login", "/test/hello").permitAll()
.anyRequest() //其他路徑,需要認證
.authenticated()
.and().csrf().disable();//關閉CSRF
}
}
8 自動登錄
8.1 自動登錄原理
8.2 自動登錄
- 創建配置類,向容器中注入PersistentTokenRepository組件。
package com.sunxiaping.springsecurity.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
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.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import javax.sql.DataSource;
/**
* SpringSecurity的配置類
*
* @author 許大仙
* @version 1.0
* @since 2020-10-28 13:38
*/
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier(value = "userDetailsService")
private UserDetailsService userDetailsService;
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Autowired
private DataSource dataSource;
/**
* 向容器中注入PersistentTokenRepository組件
*
* @return
*/
@Bean
public PersistentTokenRepository persistentTokenRepository() {
JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
jdbcTokenRepository.setDataSource(dataSource);
//自動創建表,第一次執行會創建,以后執行需要注釋掉
// jdbcTokenRepository.setCreateTableOnStartup(true);
return jdbcTokenRepository;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
//配置沒有權限訪問跳轉自定義頁面
http.exceptionHandling().accessDeniedPage("/403.html");
//添加退出的映射地址
http.logout().logoutUrl("/logout").logoutSuccessUrl("/login").permitAll();
http.formLogin() //自定義自己編寫的登錄頁面
.loginPage("/login.html") //登錄頁面設置
.usernameParameter("username")
.passwordParameter("password")
.loginProcessingUrl("/login")//登錄訪問的路徑
.defaultSuccessUrl("/success") //登錄成功,跳轉的路徑
.failureUrl("/failure")
.permitAll() //指定路徑,無需保護
.and()
.authorizeRequests()
.antMatchers("/", "/login", "/test/hello").permitAll()
.anyRequest() //其他路徑,需要認證
.authenticated()
.and().csrf().disable();//關閉CSRF
}
}
- 在配置類中,開啟記住我功能。
package com.sunxiaping.springsecurity.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
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.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import javax.sql.DataSource;
/**
* SpringSecurity的配置類
*
* @author 許大仙
* @version 1.0
* @since 2020-10-28 13:38
*/
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier(value = "userDetailsService")
private UserDetailsService userDetailsService;
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Autowired
private DataSource dataSource;
/**
* 向容器中注入PersistentTokenRepository組件
*
* @return
*/
@Bean
public PersistentTokenRepository persistentTokenRepository() {
JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
jdbcTokenRepository.setDataSource(dataSource);
//自動創建表,第一次執行會創建,以后執行需要注釋掉
// jdbcTokenRepository.setCreateTableOnStartup(true);
return jdbcTokenRepository;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
//配置沒有權限訪問跳轉自定義頁面
http.exceptionHandling().accessDeniedPage("/403.html");
//添加退出的映射地址
http.logout().logoutUrl("/logout").logoutSuccessUrl("/login").permitAll();
http.formLogin() //自定義自己編寫的登錄頁面
.loginPage("/login.html") //登錄頁面設置
.usernameParameter("username")
.passwordParameter("password")
.loginProcessingUrl("/login")//登錄訪問的路徑
.defaultSuccessUrl("/success") //登錄成功,跳轉的路徑
.failureUrl("/failure")
.permitAll() //指定路徑,無需保護
.and()
.authorizeRequests()
.antMatchers("/", "/login", "/test/hello").permitAll()
.anyRequest() //其他路徑,需要認證
.authenticated()
.and().csrf().disable();//關閉CSRF
//開啟記住我功能,並設置記住我為一周
http.rememberMe().tokenRepository(persistentTokenRepository()).userDetailsService(userDetailsService).tokenValiditySeconds(7 * 24 * 60 * 60);
}
}
- 在頁面添加記住我復選框:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>登錄頁面</title>
</head>
<body>
<form th:action="@{/login}" method="post">
用戶名: <input type="text" name="username"><br>
密碼:<input type="password" name="password"> <br>
記住我:<input type="checkbox" name="remember-me" id="">
<input type="submit" value="登錄">
</form>
</body>
</html>