SpringSecurity实现基于数据库的身份验证

1. 问题描述

基于数据库MySQL实现用户登录的身份验证,暂时不考虑权限问题;

2.技术选型

SpringBoot+SpringSecurity+SpringData JPA+MySQL;

3.Pom依赖

3.1 springboot版本

 <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.8.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
 </parent>

3.2 maven依赖

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <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>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
</dependencies>

4.application.yml配置

spring:
#  jpa
  jpa:
    show-sql: true
    hibernate:
      ddl-auto: update
    database: mysql
#  db
  datasource:
    type: com.zaxxer.hikari.HikariDataSource
    url: jdbc:mysql://localhost/yuyufeng?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
    hikari:
      driver-class-name: com.mysql.cj.jdbc.Driver
      username: root
      password: 2289288246

5.项目结构

在这里插入图片描述

6.HelloSecurityController实现

package springsecuritydemo1.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/hello")
public class HelloSecurityController {
    
    

    @GetMapping
    public String hello(){
    
    
        return "Hello Spring Security!";
    }
}

启动项目,访问HelloSecurityController的路由,由于导入了SpringSecurity依赖,会出现默认的身份验证,跳转到 路径: http://localhost:8080/login; 默认用户名是:user,密码会在控制台生成:

Using generated security password: d3f3d4ff-111a-442c-8488-d6dfd4a15475

默认登录页面:
在这里插入图片描述

7.SpringData jpa实现

7.1 UserInfo实体实现

package springsecuritydemo1.entity;

import javax.persistence.*;

@Entity(name="userInfo")
@Table(name="user_info")
public class UserInfo {
    
    
    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)//自增
    private Long id;
    //用户名
    @Column(name = "username",nullable = false)
    private String username;
    //用户密码
    @Column(name = "password",nullable = false,unique = false)
    private String password;

    public Long getId() {
    
    
        return id;
    }

    public void setId(Long id) {
    
    
        this.id = id;
    }

    public String getUsername() {
    
    
        return username;
    }

    public void setUsername(String username) {
    
    
        this.username = username;
    }

    public String getPassword() {
    
    
        return password;
    }

    public void setPassword(String password) {
    
    
        this.password = password;
    }

    @Override
    public String toString() {
    
    
        return "UserInfo{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

7.2 UserInfoRepository实现

package springsecuritydemo1.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import springsecuritydemo1.entity.UserInfo;

@Repository
public interface UserInfoRepository extends JpaRepository<UserInfo,Long> {
    
    

    UserInfo findByUsername(String username);
}

7.3 UserInfoService接口及UserInfoServiceImpl类实现
(1) UserInfoService接口

package springsecuritydemo1.service;

import springsecuritydemo1.entity.UserInfo;

public interface UserInfoService {
    
    

    UserInfo create(UserInfo userInfo);

    UserInfo findByUsername(String username);
}

(2)UserInfoServiceImpl类

package springsecuritydemo1.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import springsecuritydemo1.entity.UserInfo;
import springsecuritydemo1.repository.UserInfoRepository;
import springsecuritydemo1.service.UserInfoService;

@Service
public class UserInfoServiceImpl implements UserInfoService {
    
    

    @Autowired
    private UserInfoRepository userInfoRepository;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public UserInfo create(UserInfo userInfo) {
    
    
        //密码加密
        userInfo.setPassword(passwordEncoder.encode(userInfo.getPassword()));
        return userInfoRepository.save(userInfo);
    }

    @Override
    public UserInfo findByUsername(String username) {
    
    
        return userInfoRepository.findByUsername(username);
    }
}

7.4 数据库数据准备

package springsecuritydemo1;

import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import springsecuritydemo1.entity.UserInfo;
import springsecuritydemo1.service.UserInfoService;

@SpringBootTest
class SpringSecurityDemo1ApplicationTests {
    
    

    @Autowired
    private UserInfoService userInfoService;

    @Test
    void contextLoads() {
    
    
        UserInfo userInfo1 = new UserInfo();
        userInfo1.setId(1L);
        userInfo1.setUsername("admin");
        userInfo1.setPassword("123456");
        UserInfo userInfoPO1 = userInfoService.create(userInfo1);
        System.out.println(userInfo1);

        UserInfo userInfo2 = new UserInfo();
        userInfo2.setId(2L);
        userInfo2.setUsername("user");
        userInfo2.setPassword("123456");
        UserInfo userInfoPO2 = userInfoService.create(userInfo2);
        System.out.println(userInfo2);
    }
}

不出意外,数据库已存在上述两条数据;

8. MyUserDetailService实现(关键步骤)

创建MyUserDetailService类,实现UserDetailsService接口,重写loadUserByUsername(String s)方法,返回的UserDetails类包含了用户名、密码、权限(暂不考虑),交给SpringSecurity进行身份验证;

package springsecuritydemo1.common.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
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.Component;
import springsecuritydemo1.entity.UserInfo;
import springsecuritydemo1.service.UserInfoService;

import java.util.ArrayList;
import java.util.List;

@Component
public class MyUserDetailService implements UserDetailsService {
    
    

    @Autowired
    private UserInfoService userInfoService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
    
    
        UserInfo userInfo = userInfoService.findByUsername(s);
        if (userInfo == null) {
    
    
            throw new UsernameNotFoundException("用户不存在");
        }
        //暂时不考虑权限验证,故该权限List为空;
        List<GrantedAuthority> authorities = new ArrayList<>();

        User userDetails = new User(userInfo.getUsername(), userInfo.getPassword(), authorities);
        return userDetails;
    }
}

9.SecurityConfig类实现

创建SecurityConfig类继承WebSecurityConfigurerAdapter类,注入PasswordEncoder;

package springsecuritydemo1.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.builders.HttpSecurity;
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;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    

    @Bean
    public PasswordEncoder passwordEncoder(){
    
    
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
    
    
        super.configure(http);
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    
    
        super.configure(auth);
    }
}

10.测试

10.1 测试
访问HelloSecurityController,进入默认登录页面,输入用户名与密码(参照7.4),登录成功,验证成功。

猜你喜欢

转载自blog.csdn.net/weixin_43911286/article/details/105653674
今日推荐