Springboot整合SpringSecurity实现数据库认证

1. 导入依赖

<?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>
    <groupId>tian.project</groupId>
    <artifactId>easy_to_stop</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>easy_to_stop</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>2.3.7.RELEASE</spring-boot.version>
    </properties>

    <dependencies>
<!--        引入数据库连接依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
<!--        连接池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.24</version>
        </dependency>
<!--        Swagger2整合-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>
<!--        整合Lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
<!--        整合Mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.2</version>
        </dependency>
<!--        整合thymeleaf引擎依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

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

<!--        整合Thymeleaf与Security-->
        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-springsecurity6</artifactId>
            <version>3.1.0.M1</version>
        </dependency>
<!--        加入MD5加密需要的依赖-->

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>

        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
        </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>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>
<!--        代码自动生成器配置-->
<!--        <dependency>-->
<!--            <groupId>com.baomidou</groupId>-->
<!--            <artifactId>mybatis-plus-generator</artifactId>-->
<!--            <version>3.4.0</version>-->
<!--        </dependency>-->
<!--        <dependency>-->
<!--            <groupId>org.springframework.boot</groupId>-->
<!--            <artifactId>spring-boot-starter-freemarker</artifactId>-->
<!--        </dependency>-->

    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.3.7.RELEASE</version>
                <configuration>
                    <mainClass>tian.project.easy_to_stop.EasyToStopApplication</mainClass>
                </configuration>
                <executions>
                    <execution>
                        <id>repackage</id>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
<!--            用maven执行测试用例很简单,直接运行mvn test就可以.一般我们执行maven打包命令mvn package前maven会默认执行test-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.22.2</version>
                <configuration>
                    <skipTests>true</skipTests>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

2. 创建数据库表

CREATE TABLE `t_admin` (
  `id` bigint(19) NOT NULL COMMENT '主键',
  `admin` varchar(50) NOT NULL COMMENT '管理员账号',
  `admin_password` varchar(50) NOT NULL COMMENT '管理员密码',
  `role` varchar(50) NOT NULL COMMENT '角色',
  `locked` tinyint(1) DEFAULT '1' COMMENT '判断账户密码是否未过期',
  `check_enabled` tinyint(1) DEFAULT '1' COMMENT '判断账户是否可用',
  `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

3.配置实体类

package tian.project.easy_to_stop.pojo;

import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
import org.omg.CORBA.IDLType;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import javax.annotation.security.DenyAll;
import javax.swing.*;
import java.util.*;

/**
 * @author tian
 * @date 2022.6.2
 * @description 管理员实体类
 *
 */
@ApiModel("管理员实体类")
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "t_admin")
public class Admin implements UserDetails {
    @ApiModelProperty("主键-雪花算法策略")
    @TableId(type = IdType.ASSIGN_ID)
    private Long id;
    @ApiModelProperty("管理员账号")
    private String admin;
    @ApiModelProperty("密码")
    private String adminPassword;
    @ApiModelProperty("角色")
    private String role;
    @ApiModelProperty("当前用户是否未锁定")
    private Boolean locked;
    @ApiModelProperty("当前账户是否可用")
    private Boolean checkEnabled;
    @ApiModelProperty("创建时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @TableField(value = "gmt_create",fill = FieldFill.INSERT)//数据插入时候自动填充
    private Date gmtCreate;
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")//返回数据给前端的
    @TableField(fill = FieldFill.INSERT_UPDATE)//数据插入和更新的时候自动填充
    @ApiModelProperty("更新时间")
    private Date gmtModified;


    /**
     * 用户实体类需要实现UserDetails的接口,实现的7个方法如下:
     * 1.getAuthorities   获取当前用户对象所具有的角色信息
     * 2.getPassword() 获取当前用户对象的密码
     * 3.getUsername() 获取当前用户对象的用户名
     * 4.getAccountNonExpired() 当前用户是否未过期
     * 5.getAccountNonLocked()当前用户是否未锁定
     * 6.isCredentialsNonExpired() 当前账户密码是否未过期
     * 7.isEnable 当前账户是否可用
     */
    /*
    注意:
    用户根据实际情况设置以下方法的返回值
     */
    /**
     * getAuthorities   获取当前用户对象所具有的角色信息
     * @return
     */

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        List<SimpleGrantedAuthority> authorities=new ArrayList<>();
        //本系统只有一个角色
        authorities.add(new SimpleGrantedAuthority(role));
        return authorities;
    }

    @Override
    public String getUsername() {
        return admin;
    }

    @Override
    public String getPassword() {
        return adminPassword;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return !locked;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return checkEnabled;
    }
}

4.继承UserDetailsService

package tian.project.easy_to_stop.service;

import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Service;
import tian.project.easy_to_stop.pojo.Admin;

/**
 * @author tian
 * @date 2022.6.2
 * @description 管理员权限业务处理实现类
 *
 */
@Service
public interface AdminService extends UserDetailsService {
    /**
     * 根据管理员名获取管理员
     */
    Admin getAdminByAdmin(String name);
}

5.实现UserDetailsService

package tian.project.easy_to_stop.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
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 org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import tian.project.easy_to_stop.mapper.AdminMapper;
import tian.project.easy_to_stop.pojo.Admin;
import tian.project.easy_to_stop.service.AdminService;
import tian.project.easy_to_stop.service.UserService;

/**
 * @author tian
 * @date 2022.6.2
 * @description 管理员权限业务操作实现类
 */
@Service
@Transactional(rollbackFor = Exception.class
)
public class AdminServiceImpl implements AdminService {
    @Autowired
    AdminMapper adminMapper;
    /**
     * 定义此实现类:
     *实现该接口中的loadUserByUsername方法,该方法的参数就是用户登录时输入的用户名,
     * 通过用户名去数据库中查找用户,如果没有查找到用户,就抛出一个用户不存在的异常,通过
     * 查找到了用户,就继续查找该用户所具有的角色信息,并将获取到的user对象返回,再由系统
     * 提供的DAOAuthenticationProvider类去比对密码是否正确
     */
    @Override
    public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException {
        Admin admin=this.getAdminByAdmin(name);
        if(ObjectUtils.isEmpty(admin)){
            throw new UsernameNotFoundException("账户不存在!");
        }
        Admin getAdmin=adminMapper.selectById(admin.getId());
        UserDetails userDetails=User.withUsername(getAdmin.getAdmin())
                .password(getAdmin.getAdminPassword())
                .authorities(getAdmin.getRole())
                .build();
        System.out.println("admin:\n"+getAdmin);
        System.out.println("userDetails:\n"+userDetails.getUsername());
        System.out.println("roles:\n"+userDetails.getAuthorities());
        System.out.println("locked:\n"+userDetails.isAccountNonLocked());
        System.out.println("enabled:\n"+userDetails.isEnabled());
        System.out.println("userDetails:\n"+userDetails.getUsername());
        return userDetails;
    }


    @Override
    public Admin getAdminByAdmin(String admin) {
        QueryWrapper<Admin> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("admin",admin);
        return adminMapper.selectOne(queryWrapper);
    }
}

6.创建页面及controller映射

在这里插入图片描述

package tian.project.easy_to_stop.controller;

import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Select;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
import tian.project.easy_to_stop.constant.Constant;

import java.util.HashMap;
import java.util.Map;

@Controller
@RequestMapping("/page")
@Slf4j
public class PageController {
    /**
     * 测试
     */
    @ApiOperation("Hello World")
    @GetMapping("/helloWorld")
    public ModelAndView helloWorld(){
        ModelAndView modelAndView=new ModelAndView("helloWorld");
        modelAndView.addObject("name","你好");
        return modelAndView;
    }
    /**
     * @author tian
     * @date 2022.6.1
     * @description 管理员登录页面
     */
    @ApiOperation("管理员登录页面")
    @GetMapping("/toLogin")
    public ModelAndView toLogin(){
        log.info("进入登录页面!");
        ModelAndView modelAndView=new ModelAndView("toLogin");
        return modelAndView;
    }
    /**
     * @author tian
     * @date 2022.6.1
     * @description 菜单页面
     */
    @ApiOperation("views管理页面")
    @GetMapping("/views/{page}")
    public ModelAndView menu(@PathVariable("page") String page){
        ModelAndView modelAndView=new ModelAndView("views/"+page);
        log.info("进入页面!{}",modelAndView);
        return modelAndView;
    }
}

7.配置SecurityConfig

package tian.project.easy_to_stop.config;

import org.springframework.beans.factory.annotation.Autowired;
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.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.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.Md4PasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.util.ObjectUtils;
import tian.project.easy_to_stop.constant.Constant;
import tian.project.easy_to_stop.service.AdminService;
import tian.project.easy_to_stop.service.UserService;
import tian.project.easy_to_stop.service.impl.AdminServiceImpl;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * 配置Security-AOP
 */
@Configuration
@EnableWebSecurity //开启Spring Security 的权限控制和认证功能
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private AdminService adminService;
    /**基于内存认证*/
    //链式编程
    /**
     * 授权
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //登录页所有人可以访问,功能页管理员可以访问
        http.authorizeRequests()
                .antMatchers("/").permitAll()
                .antMatchers("/page/views/**").hasRole("admin1")
                .and()
                .formLogin().loginPage("/page/toLogin")
                .usernameParameter("admin")
                .passwordParameter("password")
                .permitAll()
                .defaultSuccessUrl("/page/views/menu")
                .failureUrl("/page/toLogin")
                .and().logout().logoutSuccessUrl("/page/toLogin")
                .invalidateHttpSession(true)
                .clearAuthentication(true)
                .permitAll()
                .and()
                .csrf().disable();


    }

    @Bean
    PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
    /**
     * 认证
     * 密码编码:PasswordEncoder
     * 在Spring Security 5.0+中新增了很多的加密方法
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        //基于数据库认证
        auth.userDetailsService(adminService).passwordEncoder(passwordEncoder());
//        //这些数据正常从数据库认证,也可以从内存认证
//        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
//                .withUser("admin")
//                .password(new BCryptPasswordEncoder().encode("123456"))
//                .roles("admin1");
    }
    /**配置登录成功及失败得的事项*/
//    /登录成功的处理器
//            .successHandler(new AuthenticationSuccessHandler() {
//
//        @Override
//        public void onAuthenticationSuccess(HttpServletRequest httpServletRequest,
//                HttpServletResponse httpServletResponse,
//                Authentication authentication)
//                            throws IOException, ServletException {
//
//        }
//    })
//            .failureHandler(new AuthenticationFailureHandler() {
//
//        @Override
//        public void onAuthenticationFailure(HttpServletRequest httpServletRequest,
//                HttpServletResponse httpServletResponse,
//                AuthenticationException e)
//                            throws IOException, ServletException {
//
//        }
//    })
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

锐行织梦者

谢谢您的支持!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值