SpringSecurity Web 权限方案
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>