Spring Boot安全管理

  • Post author:
  • Post category:其他






一.Spring Security




快速⼊⻔




1.




添加




security




启动器


在项⽬的


pom.xml


⽂件中引⼊


Spring Security


安全框架的依赖启动器


spring-boot-starter-security




<!– Spring Security


提供的安全管理依赖启动器


–>

<dependency>

<groupId>


org.springframework.boot


</groupId>

<artifactId>


spring-boot-starter-security


</artifactId>

</dependency>

上述引⼊的依赖


spring-boot-starter-security


就是


Spring Boot


整合


Spring Security


安全框架⽽提供的依赖启动器,

其版本号由


Spring Boot


进⾏统⼀管理。需要说明的是,⼀旦项⽬引⼊


spring-boot-starter-security


启动器,


MVC

Security





WebFlux Security


负责的安全功能都会⽴即⽣效(


WebFlux Security


⽣效的另⼀个前提是项⽬属于

WebFlux Web


项⽬);对于


OAuth2


安全管理功能来说,则还需要额外引⼊⼀些其他安全依赖。



项⽬启动测试


项⽬启动时会在控制台⾃动⽣成⼀个安全密码(


security password


这个密码在每次启动项⽬时都是随机⽣成

的)。通过在浏览器访问


http://localhost:8080


查看项⽬⾸⻚,效果如下图所示。


这种默认安全管理⽅式存在诸多问题。例如,只有唯⼀的默认登录⽤户user


,密码随机⽣成且过于暴露、登录⻚⾯ 及错误提示⻚⾯不是我们想要的等。



1.MVC Security




安全配置介绍



1.下⾯我们通过


Spring Security API


查看


WebSecurityConfigurerAdapter


的主要⽅法,具体如下表

@EnableWebSecurity // 开启MVC Security安全⽀持
public class SecurityConfig extends WebSecurityConfigurerAdapter {

//定制基于HTTP请求的⽤户访问控制
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
    }
//定制⽤户认证管理器来实现⽤户认证
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        super.configure(auth);
    }
}







4




⾃定义⽤户认证



1.In-Memory Authentication:内存身份认证


2.JDBC Authentication:


JDBC


身份认证


3.UserDetailsService:身份详情服务


4.LDAP Authentication:


LDAP


身份认证


5.AuthenticationProvider:身份认证提供商



4.1.2 使⽤内存进⾏身份认证   写一个配置类即可


package com.cy.config;
import
org.springframework.security.config.annotation.authentication.builders.AuthenticationMa
nagerBuilder;
import
org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import
org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerA
dapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
/**
* MVC Security管理配置的⾃定义WebSecurityConfigurerAdapter类
*/
@EnableWebSecurity // 开启MVC Security安全⽀持
public class SecurityConfig extends WebSecurityConfigurerAdapter {
 /** ⽤户身份认证⾃定义配置 */
 @Override
 protected void configure(AuthenticationManagerBuilder auth) throws Exception {
 // 密码需要设置编码器
 BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
 // 1.使⽤内存⽤户信息,作为测试使⽤(设置⽤户名、密码和⻆⾊)
 auth.inMemoryAuthentication().passwordEncoder(encoder)
.withUser("tom").password(encoder.encode("123456")).roles("common")
 .and()
 .withUser("李四").password(encoder.encode("123456")).roles("vip");
 }
}

(1)





Spring Security 5


开始,⾃定义⽤户认证必须设置密码编码器⽤于保护密码,否则控制台会出现

“IllegalArgumentException: There is no PasswordEncoder mapped for the id “null””


异常错误。

(2) Spring Security


提供了多种密码编码器,包括


BCryptPasswordEncoder





Pbkdf2PasswordEncoder




ScryptPasswordEncoder


等。

(3)


⾃定义⽤户认证时,可以定义⽤户⻆⾊


roles


,也可以定义⽤户权限


authorities


。在进⾏赋值时,权限通常是在

⻆⾊值的基础上添加


ROLE_


前缀。例如,


roles(“common”)





authorities(“ROLE_common”)


是等效的。

(4)


⾃定义⽤户认证时,可以为某个⽤户⼀次指定多个⻆⾊或权限,例如,


roles(“common”, “vip”)




authorities(“ROLE_common”, “ROLE_vip”)



4.3 UserDetailsService




身份认证


1.

1.


在项⽬的


pom.xml


⽂件中添加Mybaits


依赖启动器和


lombok


依赖。

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.2</version>
</dependency>


<dependency>

<groupId>


org.projectlombok


</groupId>

<artifactId>


lombok


</artifactId>

</dependency>
package com.example.demo.service.imp;

import com.example.demo.pojo.Authority;
import com.example.demo.pojo.Customer;
import com.example.demo.service.CustomerService;
import org.springframework.beans.factory.annotation.Autowired;
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.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
/** ⾃定义⼀个UserDetailsService接⼝实现类进⾏⽤户认证信息封装 */
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
    @Autowired
    /* 内有提供自定义用户查询和权限查询的方法
    * getCustomer  根据名字查询用户信息 的方法
    * 
    * getCustomerAuthority  根据名字查询用户权限 的方法
    * */
    
    private CustomerService customerService;
    @Override
    public UserDetails loadUserByUsername(String username) throws
            UsernameNotFoundException {
        // 通过业务⽅法获取⽤户及权限信息
        Customer customer = customerService.getCustomer(username);
        List<Authority> authorities = customerService.getCustomerAuthority(username);
        // 对⽤户权限进⾏封装
        List<SimpleGrantedAuthority> list = authorities.stream().map(authority -> new
                SimpleGrantedAuthority(authority.getAuthority())).collect(Collectors.toList());
        // 返回封装的UserDetails⽤户详情类
        if (customer != null) {
            UserDetails userDetails = new User(customer.getUsername(),
                    customer.getPassword(), list);
            return userDetails;
        } else {
            // 如果查询的⽤户不存在(⽤户名不存在),必须抛出此异常
            throw new UsernameNotFoundException("当前⽤户不存在!");
        }}}
package com.example.demo.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.WebSecurityConfigurer;
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 javax.sql.DataSource;
import java.util.Date;
import java.util.HashMap;

//开启安全管理的支持
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired //Hikari连接池,自动将mysql配置信息加载连接池对象上
    private DataSource dataSource;
    //1.用户身份认证的配置
    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests() // 开启基于HttpServletRequest请求访问的限制
                .antMatchers("/").permitAll() // 开启Ant⻛格的路径匹配。⽆条件对请求进⾏放⾏
                .antMatchers("/login/**").permitAll()
                .antMatchers("/detail/common/**").hasRole("common") // 匹配⽤户是否有某⼀个⻆⾊
                .antMatchers("/detail/vip/**").hasRole("vip")
                .anyRequest().authenticated()// 匹配任何请求。匹配已经登录认证的⽤户
                .and() // 功能连接符
                .formLogin(); // 开启基于表单的⽤户登录
              http.formLogin() // 开启基于表单的⽤户登录
                // ⽤户登录⻚⾯跳转路径,默认为get请求的/login。⽆条件对请求进⾏放⾏
                .loginPage("/userLogin").permitAll()
                .usernameParameter("name") // 登录⽤户的⽤户名参数, 默认为username
                .passwordParameter("pwd") // 登录⽤户的密码参数,默认为password
                .defaultSuccessUrl("/") // ⽤户直接登录后默认跳转地址
                .failureUrl("/userLogin?error"); // ⽤户登录失败后的跳转地址,默认为/login?erro
        // ⾃定义⽤户退出控制
        http.logout()
                .logoutUrl("/mylogout")
                .logoutSuccessUrl("/");

        // 定制Remember-me记住我功能
        http.rememberMe()
                .rememberMeParameter("rememberme")
                .tokenValiditySeconds(200)
                // 对Cookie信息进⾏持久化管理
                .tokenRepository(tokenRepository());
    }
 
    @Bean
    /** 持久化Token存储 */
    public JdbcTokenRepositoryImpl tokenRepository() {
        JdbcTokenRepositoryImpl jti = new JdbcTokenRepositoryImpl();
        jti.setDataSource(dataSource);
        //自动创建数据库表字段
        jti.setCreateTableOnStartup(true);
        return jti;
    }
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 密码需要设置编码器
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();

        auth.userDetailsService(userDetailsService).passwordEncoder(encoder);

    }
    }

完成以上配置基于


内存进⾏身份认证




就结束了

接下来是配置的信息


HttpSecurity类的主要⽅法及说明:

方法 描述

authorizeRequests()

开启基于


HttpServletRequest


请求访问的限制

formLogin()

开启基于表单的⽤户登录

httpBasic()

开启基于


HTTP


请求的


Basic


认证登录

logout()

开启退出登录的⽀持

sessionManagement()

开启


Session


管理配置

rememberMe()

开启记住我功能

csrf()

配置


CSRF


跨站请求伪造防护功能

⽤户请求控制相关的主要⽅法及说明



⽅法



描述


antMatchers(java.lang.String… antPtterns)

开启


Ant


⻛格的路径匹配

mvcMatchers(java.lang.String… patterns)

开启


MVC


⻛格的路径匹配(与


Ant


⻛格类似)

regexMatchers(java.lang.Sring…

regexPatterns)

开启正则表达式的路径匹配

and()

功能连接符

anyRequest()

匹配任何请求

rememberMe()

开启记住我功能

access(String attribute)

匹配给定的


SpEL


表达式计算结果是否为


true

hasAnyRole(String… roles)

匹配⽤户是否有参数中的任意⻆⾊

hasRole(Sring role)

匹配⽤户是否有某⼀个⻆⾊

hasAnyAuthority(String… authorities)

匹配⽤户是否有参数中的任意权限

hasAuthority(String authority)

匹配⽤户是否有某⼀个权限

authenticated()

匹配已经登录认证的⽤户

fullyAuthenticated()

匹配完整登录认证的⽤户(⾮


rememberMe


登录⽤ 户)

hasIpAddress(String ipAddressExpression)

匹配某


IP


地址的访问请求

permitAll()

⽆条件对请求进⾏放⾏

formLogin()⽤户登录⽅法中涉及⽤户登录的主要⽅法及说明如下表所示



⽅法



描述


loginPage(String loginPage)

⽤户登录⻚⾯跳转路径,默认为


get


请 求的/login

successForwardUrl(String forwardUrl)

⽤户登录成功后的重定向地址

successHandler(AuthenticationSuccessHandler

authenticationSuccessHandler)

⽤户登录成功后的处理

defaultSuccessUrl(String defaultSuccessUrl)

⽤户直接登录后默认跳转地址

failureForwardUrl(String forwardUrl)

⽤户登录失败后的重定向地址

failureUrl(String authenticationFailureUrl)

⽤户登录失败后的跳转地址,默认




/login?error

failureHandler(AuthenticationFailureHandler

authenticationFailureHandler)

⽤户登录失败后的错误处理

usernameParameter(String usernameParameter)

登录⽤户的⽤户名参数, 默认为

username

passwordParameter(String passwordParameter)

登录⽤户的密码参数,默认为

password

loginProcessingUrl(String loginProcessingUrl)

登录表单提交的路径,默认为


post




求的


/login

permitAll()

permitAll()

⽆条件对请求进⾏放⾏


rememberMe()记住我功能相关涉及记住我的主要⽅法及说明如下表所示




⽅法



描述


rememberMeParameter(String rememberMeParameter)

指示在登录时记住⽤户的


HTTP


参数

key(String key)

记住我认证⽣成的


Token


令牌标识

tokenValiditySeconds(int tokenValiditySeconds)

记住我


Token


令牌有效期,单位为秒

tokenRepository(PersistentTokenRepository

tokenRepository)

指定要使⽤的


PersistentTokenRepository


,⽤来配置持久化


Token


令牌

alwaysRemember(boolean alwaysRemember)

是否应该始终创建记住我


Cookie


,默认为


false

clearAuthentication(boolean clearAuthentication)

是否设置


Cookie


为安全的,如果设置为


true


,则必须通过


HTTPS


进⾏连接请 求

Spring Security安全框架提供了CSRF防御相关⽅法




⽅法



描述


disable()

关闭


Security


默认开启的


CSRF


防御功能

csrfTokenRepository(CsrfTokenRepository

csrfTokenRepository)

指定要使⽤的


CsrfTokenRepository





Token


令牌持久化仓库)。默认是由

LazyCsrfTokenRepository


包装的


HttpSessionCsrfTokenRepository

requireCsrfProtectionMatcher(RequestMatcher

requireCsrfProtectionMatcher)

指定针对什么类型的请求应⽤


CSRF


防护功能。默认设置是忽略


GET





HEAD





TRACE





OPTIONS




求,⽽处理并防御其他所有请求

以上就是一些比较常用的配置信息





版权声明:本文为weixin_62907807原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。