zoukankan      html  css  js  c++  java
  • 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

    在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文件:

    在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>
    
  • 相关阅读:
    【RS】Automatic recommendation technology for learning resources with convolutional neural network
    卷积神经网络的入门
    Debug 路漫漫-10:AttributeError: 'Embedding' object has no attribute 'get_shape'
    Debug 路漫漫-09:构建CNN时维度不一致问题
    Debug 路漫漫-08:Keras 版本升级函数变换导致的问题
    springboot 过滤器、拦截器、消息转换器、切片执行顺序 及区别
    java InputStream读取数据问题
    Springboot 2-OAuth 2修改登录加密方式
    Spring Boot Security Oauth2之客户端模式及密码模式实现
    oauth2.0通过JdbcClientDetailsService从数据库读取相应的配置
  • 原文地址:https://www.cnblogs.com/xuweiweiwoaini/p/13897385.html
Copyright © 2011-2022 走看看