Spring Security--连接数据库

简介: 连接数据库

 书接上一篇,在实际的开发中,我们的账号密码不可能是这样写在配置文件中的,应该是要来自于数据库。

接着上一篇的项目,我们继续,在原有的依赖的基础上新增,mysql驱动依赖和mybatis依赖

<dependencies>

   <dependency>

       <groupId>org.springframework.boot</groupId>

       <artifactId>spring-boot-starter-security</artifactId>

   </dependency>

   <dependency>

       <groupId>org.mybatis.spring.boot</groupId>

       <artifactId>mybatis-spring-boot-starter</artifactId>

       <version>3.0.2</version>

   </dependency>

   <dependency>

       <groupId>mysql</groupId>

       <artifactId>mysql-connector-java</artifactId>

       <version>5.1.49</version>

   </dependency>

   <dependency>

       <groupId>org.springframework.boot</groupId>

       <artifactId>spring-boot-starter-web</artifactId>

   </dependency>

</dependencies>


在数据库新建一张用户表

image.gif

我们简单一点,就4个字段

image.gif

添加一条数据,在security中,你的密码默认是加密的,不加密在密码前加(noop)

现在我们要用这个账号密码去登录,我们一步一步来操作一下。

先配置一下数据库配置:

image.gif

然后我们需要一个实体类

image.gif

user实现UserDetails 接口,重写里面的方法

package com.example.demo.model;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
/**
 * 定义用户对象,需要实现UserDetails 接口,对于Spring Security框架而言,所有的用户对象都是一个UserDetails 的实例
 *
 * 根据自己实际情况,实现接口里的方法
 */
public class User implements UserDetails {
    private Integer id;
    private String username;
    private String password;
    private Boolean enabled;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public void setEnabled(Boolean enabled) {
        this.enabled = enabled;
    }
    /**
     * 用来放回当前用户的角色/权限信息
     * @return
     */
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return null;
    }
    /**
     * 获取用户的密码
     * @return
     */
    @Override
    public String getPassword() {
        return password;
    }
    /**
     * 获取用户的用户名
     * @return
     */
    @Override
    public String getUsername() {
        return username;
    }
    /**
     * 账户是否没有过期(true是未过期,false是过期)
     * @return
     */
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }
    /**
     * 账户是否没有被锁定(true是未被锁定,false是已锁定)
     * @return
     */
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }
    /**
     * 密码是否没有过期
     * 一些公司邮件系统密码要求半年修改一次,不改就无法登录
     * @return
     */
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }
    /**
     * 账户是否可用
     * @return
     */
    @Override
    public boolean isEnabled() {
        return enabled;
    }
}

image.gif

我们的user对象就已经写好了

接下来写一个userservice,image.gif

同样这个接口也要实现一个UserDetailsService接口

代码如下

package com.example.demo.service;
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;
@Service
public class UserService implements UserDetailsService {
    /**
     * 根据用户名查询用户对象
     * @param username //用户登录时输入的用户名
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        return null;
    }
}

image.gif

然后来一个mapper,

image.gif

将UserMapper 注入到UserService中

package com.example.demo.service;
import com.example.demo.mapper.UserMapper;
import com.example.demo.model.User;
import org.springframework.beans.factory.annotation.Autowired;
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;
@Service
public class UserService implements UserDetailsService {
    @Autowired
    UserMapper userMapper;
    /**
     * 根据用户名查询用户对象
     * @param username //用户登录时输入的用户名
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User u = userMapper.loadUserByUsername(username);
        if (u == null){
            //说明用户名不存在
            throw new UsernameNotFoundException("账号不存在");
        }
        return u;
    }
}

image.gif

UserMapper如下

package com.example.demo.mapper;
import com.example.demo.model.User;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserMapper {
    User loadUserByUsername(String username);
}

image.gif

UserMapper.xml如下

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/schema/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.UserMapper">
    <select id="loadUserByUsername" resultType="com.example.demo.model.User">
        select * from user where username=#{username};
    </select>
</mapper>

image.gif

最后在pom文件的build里加

<build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

image.gif

运行成功

输入账号,密码登录,运行成功。

image.gif

这里报404,是因为没有这个页面。

附带说一下

如果是boot2.x版本,5.x的security会出现一个

java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"

的错误

这个时候新建两个类就行了

package org.ikun.security_demo;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
@Component
public class MyPasswordEncoder implements PasswordEncoder {
    @Override
    public String encode(CharSequence rawPassword) {
        return rawPassword.toString();
    }
    @Override
    public boolean matches(CharSequence rawPassword, String encodedPassword) {
        return encodedPassword.equals(rawPassword.toString());
    }
}

image.gif

package org.ikun.security_demo;
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.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //设置登录,注销,表单登录不用拦截,其他请求要拦截
        http.authorizeRequests().antMatchers("/").permitAll()
                .anyRequest().authenticated()
                .and()
                .logout().permitAll()
                .and()
                .formLogin();
        //关闭默认的csrf认证
        http.csrf().disable();
    }
    @Override
    public void configure(WebSecurity web) throws Exception {
        //设置静态资源不要拦截
        web.ignoring().antMatchers("/js/**","/css/**","/images/**");
    }
}

image.gif


相关文章
|
1月前
|
存储 Go API
使用GoFrame连接和操作TDengine时序数据库
通过使用GoFrame框架和TDengine Go驱动,我们可以方便地连接和操作TDengine时序数据库。无论是插入、查询还是分析时序数据,都可以通过简单的API调用来实现。GoFrame提供了强大的Web开发功能,结合TDengine的高性能时序数据存储和查询能力,可以构建高效、可扩展的时序数据应用。
|
2月前
|
缓存 NoSQL Java
【Azure Redis 缓存】示例使用 redisson-spring-boot-starter 连接/使用 Azure Redis 服务
【Azure Redis 缓存】示例使用 redisson-spring-boot-starter 连接/使用 Azure Redis 服务
|
29天前
|
NoSQL 关系型数据库 PHP
php连接数据库
要使用PHP连接PolarDB或MongoDB数据库,需先准备连接信息,并编写相应代码。对于PolarDB,需设置主机地址、端口、数据库名及凭据,使用`pg_connect`函数建立连接;而对于MongoDB副本集,需安装MongoDB PHP驱动,通过`MongoDB\Client`连接指定的副本集实例。请确保替换示例代码中的占位符为实际值,并正确配置副本集名称和主机信息。更多详细信息与示例代码,请参考相关链接。
134 72
|
8天前
|
关系型数据库 MySQL 数据库
6-2|测试连接数据库的命令
6-2|测试连接数据库的命令
|
8天前
|
SQL 关系型数据库 MySQL
ThinkPHP6 连接使用数据库,增删改查,find,select,save,insert,insertAll,insertGetId,delete,update方法的用法
本文介绍了在ThinkPHP6框架中如何连接和使用数据库进行增删改查操作。内容包括配置数据库连接信息、使用Db类进行原生MySQL查询、find方法查询单个数据、select方法查询数据集、save方法添加数据、insertAll方法批量添加数据、insertGetId方法添加数据并返回自增主键、delete方法删除数据和update方法更新数据。此外,还说明了如何通过数据库配置文件进行数据库连接信息的配置,并强调了在使用Db类时需要先将其引入。
ThinkPHP6 连接使用数据库,增删改查,find,select,save,insert,insertAll,insertGetId,delete,update方法的用法
|
8天前
|
SQL 关系型数据库 数据库连接
php连接数据库之PDO,PDO的简单使用和预定义占位符的使用以及PDOStatement对象的使用,占位符的不同形式,bindValue和bindParam绑定预定义占位符参数的区别
本文介绍了PHP中PDO(PHP Data Objects)扩展的基本概念和使用方法。内容包括PDO类和PDOStatement类的介绍,PDO的简单使用,预定义占位符的使用方法,以及PDOStatement对象的使用。文章还讨论了绑定预定义占位符参数的不同形式,即bindValue和bindParam的区别。通过具体示例,展示了如何使用PDO进行数据库连接、数据查询、数据插入等操作。
php连接数据库之PDO,PDO的简单使用和预定义占位符的使用以及PDOStatement对象的使用,占位符的不同形式,bindValue和bindParam绑定预定义占位符参数的区别
|
8天前
|
SQL 关系型数据库 MySQL
php学习笔记-连接操作mysq数据库(基础)-day08
本文介绍了PHP中连接操作MySQL数据库的常用函数,包括连接服务器、设置字符集、关闭连接、选择数据库、结果集释放、获取影响行数以及遍历结果集等操作。通过书籍查询的实例演示了如何使用这些函数进行数据库操作,并提供了一个PHP操纵MySQL数据库的模板。
php学习笔记-连接操作mysq数据库(基础)-day08
|
11天前
|
SQL JavaScript 关系型数据库
Node服务连接Mysql数据库
本文介绍了如何在Node服务中连接MySQL数据库,并实现心跳包连接机制。
25 0
Node服务连接Mysql数据库
|
2月前
|
SQL 数据库
Spring5入门到实战------13、使用JdbcTemplate操作数据库(批量增删改)。具体代码+讲解 【下篇】
这篇文章是Spring5框架的实战教程,深入讲解了如何使用JdbcTemplate进行数据库的批量操作,包括批量添加、批量修改和批量删除的具体代码实现和测试过程,并通过完整的项目案例展示了如何在实际开发中应用这些技术。
Spring5入门到实战------13、使用JdbcTemplate操作数据库(批量增删改)。具体代码+讲解 【下篇】
|
2月前
|
SQL Java 数据库连接
Java开发者必知:JDBC连接数据库的“三大法宝”
Java开发者必知:JDBC连接数据库的“三大法宝”
19 7
下一篇
无影云桌面