初看Spring Security一脸懵逼,看懂直接跪下

简介: 初看Spring Security一脸懵逼,看懂直接跪下

Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架, 提供了完善的认证机制和方法级的授权功能。是一款非常优秀的权限管理框架。它的核心是一组过滤器链,不同的功能经由不同的过滤器。 今天通过一个简单的案例了解一下Spring Security的基本用法

引入依赖

在项目中引入Spring Security依赖,代码如下:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

引入依赖后,整个项目都被Spring Security保护起来,所有的接口都要登录之后才能访问了,例如,我需要访问/doc.html接口文档,直接跳到登录页面。如下图:

这时,你会有十万个为什么啦?这个页面哪里的?这个用户名和密码是啥?等等。不着急,听我一一道来。

用户名和密码在哪里设置?

当我们引入了Spring Secruity依赖后,启动项目之后,密码就会在控制台中输出的,格式是UUID,每一次启动密码都不一样的,而用户名是默认是User的。

Using generated security password: 8b2d752b-8892-4cd3-a7a9-a36e79e1cad8

我们可以通过项目的配置文件自定义用户名和密码的,代码如下,这样每次重启项目,用户名和密码都是固定不变的。

spring:
  security:
      user:
        name: didiplus
        password: didiplus

UserDetailsService接口详解

UserDetailsService接口只有一个抽象方法就是loadUserByUsername(String username)。代码如下:

public interface UserDetailsService {
   
   

    UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;

}

UserDetailsService接口的返回值是UserDetails接口, 这又是一个接口,Spring Security框架提供了它的实现类org.springframework.security.core.userdetails包下的User类对象 。userdetails源码如下:

Spring Security提供了三个UserDetailsService接口的实现类,分别是CachingUserDetailsServiceJdbcDaoImplInMemoryUserDetailsManager

JdbcDaoImpl实现类


该实现类是通过数据库获取用户名和密码,JdbcUserDetailsManager中定义了一大堆SQL语句,如下:

接着我们在看一下JdbcDaoImpl中的loadUsersByUsername方法,如下:

InMemoryUserDetailsManager实现类


以上代码是判断内存中的HashMap集合中是否有用户数据对应的User对象,如果没有,直接抛出异常,如果有就返回该用户的User对象信息。

以上代码是把配置文件中的User相关信息读取到。通过分析源码发现 Spring Security框架完成用户登录认证的核心就在与org.springframework.security.core.userdetails包下的UserDetailsService接口。

自定义实现类实现UserDetailsService接口

自定义实现类MyUserDetailsServiceImpl,代码如下:

@Service
public class MyUserDetailsServiceImpl implements UserDetailsService {
   
   

    private static  final  String USERNAME="admin";
    private static  final  String PASSWORD="admin123";



    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
   
   
        if (!USERNAME.equals(username)){
   
   
            throw new UsernameNotFoundException("用户名不存在");
        }
        UserDetails userDetails =  new User(USERNAME,PASSWORD, AuthorityUtils.commaSeparatedStringToAuthorityList("admin,common"));
        return userDetails;
    }
}

重启项目看看,输入定义的用户名和密码,发现登录不了,查看控制台发现报错,提示如下:

报错的原因是没有使用任何的PasswordEncoder,我们输入的密码没有用加密工具进行加密 。 Spring Security其实已经给我们提供了很多的PasswordEncoder 。 在org.springframework.security.crypto.password包下有一个PasswordEncoder接口,看看他的实现类

把这个PasswordEncoder的任意一个我们需要用来加密密码的实现类的Bean注入到容器里面,就可以直接拿来使用 ,代码如下:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
   
   

    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder(){
   
   
        return new BCryptPasswordEncoder();
    }
}

修改MyUserDetailsServiceImpl类如下:

@Service
public class MyUserDetailsServiceImpl implements UserDetailsService {
   
   

    private static  final  String USERNAME="admin";
    private static  final  String PASSWORD="admin123";

    @Resource
    BCryptPasswordEncoder cryptPasswordEncoder;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
   
   
        if (!USERNAME.equals(username)){
   
   
            throw new UsernameNotFoundException("用户名不存在");
        }
        UserDetails userDetails =  new User(USERNAME,cryptPasswordEncoder.encode(PASSWORD), AuthorityUtils.commaSeparatedStringToAuthorityList("admin,common"));
        return userDetails;
    }
}

重启项目再次测试,输入定义的账号和密码。即可访问到接口文档页面。

如何修改登录页面?

觉得默认的登录页面很丑,我们如何定义自己的登录页面呢?方法也很简单,首先我们先去准备一个登录页面。如下:

前端代码如下:

<form action="/login" class="login-form" >
    <h1>登录</h1>

    <div class="txtb">
        <input type="text" name="user">
        <span data-placeholder="Username"></span>
    </div>

    <div class="txtb">
        <input type="password" name="pass">
        <span data-placeholder="Password"></span>
    </div>
    <input type="submit" class="logbtn" value="登录">

    <div class="bottom-text">
        Don't have account? <a href="#">Sign up</a>
    </div>

</form>

把登录页面文件存放到项目的资源文件夹中static目录下,然后在SecurityConfig重写configure(HttpSecurity http)这个方法,代码如下:


    @Override
    protected void configure(HttpSecurity http) throws Exception {
   
   
        http.formLogin()
                .loginPage("/login.html") #自定义登录页面
                .usernameParameter("user") #对应前端表达name属性
                .passwordParameter("pass") #对应前端表达name属性
                .loginProcessingUrl("/login")
                .defaultSuccessUrl("/doc.html") #登录成功后跳转的页面地址
                .failureUrl("/login?error=true")
                .and()
                .authorizeRequests()
                .antMatchers("/login.html").permitAll() #放通登录页面
                .anyRequest().authenticated(); #其他请求都要认证
        http.csrf().disable();
    }

重新启动项目,输入定义的用户名和密码,登录成功直接跳转到/doc.html

antMatchers("url").permitAll() 是把某个url放通,不需要登录就能访问。

目录
相关文章
|
4月前
|
安全 Java 数据安全/隐私保护
使用Spring Security实现细粒度的权限控制
使用Spring Security实现细粒度的权限控制
|
4月前
|
安全 Java 数据库
实现基于Spring Security的权限管理系统
实现基于Spring Security的权限管理系统
|
4月前
|
安全 Java 数据安全/隐私保护
解析Spring Security中的权限控制策略
解析Spring Security中的权限控制策略
|
5月前
|
JSON 安全 Java
Spring Security 6.x 微信公众平台OAuth2授权实战
上一篇介绍了OAuth2协议的基本原理,以及Spring Security框架中自带的OAuth2客户端GitHub的实现细节,本篇以微信公众号网页授权登录为目的,介绍如何在原框架基础上定制开发OAuth2客户端。
202 4
Spring Security 6.x 微信公众平台OAuth2授权实战
|
5月前
|
存储 安全 Java
Spring Security 6.x OAuth2登录认证源码分析
上一篇介绍了Spring Security框架中身份认证的架构设计,本篇就OAuth2客户端登录认证的实现源码做一些分析。
228 2
Spring Security 6.x OAuth2登录认证源码分析
|
5月前
|
安全 Java 数据安全/隐私保护
Spring Security 6.x 一文快速搞懂配置原理
本文主要对整个Spring Security配置过程做一定的剖析,希望可以对学习Spring Sercurity框架的同学所有帮助。
259 5
Spring Security 6.x 一文快速搞懂配置原理
|
5月前
|
安全 Java API
Spring Security 6.x 图解身份认证的架构设计
【6月更文挑战第1天】本文主要介绍了Spring Security在身份认证方面的架构设计,以及主要业务流程,及核心代码的实现
83 1
Spring Security 6.x 图解身份认证的架构设计
|
4月前
|
安全 Java 数据安全/隐私保护
使用Spring Security实现细粒度的权限控制
使用Spring Security实现细粒度的权限控制
|
4月前
|
安全 Java 数据安全/隐私保护
使用Java和Spring Security实现身份验证与授权
使用Java和Spring Security实现身份验证与授权
|
4月前
|
存储 安全 Java
Spring Security在企业级应用中的应用
Spring Security在企业级应用中的应用