spring security 使用数据库中的账户和密码认证

示例工程地址

一、原理分析

前台的登录请求发送到后端后会由spring security进行拦截,即controller层由框架自己提供。这样用户名和密码的认证就需要在service层完成,所以框架需要在service层获取到我们自己的数据库账号信息。

spring security 提供了一个接口 **UserDetailsService **来让用户提供账号和密码,其内容如下

public interface UserDetailsService {
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}

用户实现这个接口中的loadUserByUsername方法,通过数据库中查询的账号和密码构造一个UserDetails对象返回给spring security,然后框架自己完成认证操作。

其中UserDetails也是一个接口,spring security用它来封装当前进行认证的用户信息

public interface UserDetails extends Serializable {
Collection<? extends GrantedAuthority> getAuthorities();
String getPassword();
String getUsername();
boolean isAccountNonExpired();
boolean isAccountNonLocked();
boolean isCredentialsNonExpired();
boolean isEnabled();
}

spring security 自己提供了一个实现类我们可以直接使用,以下是User中的部分代码

public class User implements UserDetails, CredentialsContainer {
private String password;
private final String username;
private final Set<GrantedAuthority> authorities;
private final boolean accountNonExpired; //帐户是否过期
private final boolean accountNonLocked; //帐户是否锁定
private final boolean credentialsNonExpired; //认证是否过期
private final boolean enabled; //帐户是否可用

所以,使用数据库完成认证的关键就是实现UserDetailsService接口,并在loadUserByUsername方法中封装一个框架需要的UserDetails对象,即User对象返回给框架,由框架完成后续的认证操作。

同时需要在spring security的配置文件中指定要用来认证的userService 的bean

二、代码实现

1.新建一个javaWeb工程

新建一个javaweb工程,导入相关依赖,pom文件的内容如下

pom文件

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>com.lyy</groupId>
<artifactId>spring_security_1</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging> <name>spring_security_1 Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.version>5.0.2.RELEASE</spring.version>
<slf4j.version>1.6.6</slf4j.version>
<log4j.version>1.2.12</log4j.version>
<mysql.version>5.1.6</mysql.version>
<mybatis.version>3.4.5</mybatis.version>
<spring.security.version>5.0.1.RELEASE</spring.security.version>
</properties> <dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.8</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version> </dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency> <dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency> <!-- log start -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency> <!-- log end --> <dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency> <dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.1.2</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>${spring.security.version}</version>
</dependency> <dependency>
<groupId>javax.annotation</groupId>
<artifactId>jsr250-api</artifactId>
<version>1.0</version>
</dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.7</version>
</dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.7</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.16</version>
</dependency>
</dependencies> <build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<configuration>
<port>80</port>
<path>/</path>
<uriEncoding>UTF-8</uriEncoding>
<server>tomcat7</server>
</configuration>
</plugin> </plugins>
</build>
</project>

在web.xml中配置spring security的过滤器

web.xml

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0"> <display-name>spring security 01</display-name> <context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-security.xml,classpath*:applicationContext.xml</param-value>
</context-param> <!-- 配置监听器 -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener> <filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping> <!-- 解决中文乱码过滤器 -->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping> <welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>

整合spring和mybatis,spring的配置文件applicationContext.xml

spring配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- 开启注解扫描,管理service和dao -->
<context:component-scan base-package="com.lyy.service">
</context:component-scan>
<context:component-scan base-package="com.lyy.dao"> </context:component-scan> <context:property-placeholder location="classpath:db.properties"/>
<!-- 配置连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean> <!--配置SqlSessionFactory工厂-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="typeAliasesPackage" value="com.lyy.domain"/>
</bean> <!--配置Dao接口所在包-->
<bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.lyy.dao"/>
</bean> <!-- 配置Spring的声明式事务管理 -->
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean> <tx:annotation-driven transaction-manager="transactionManager"/>
</beans>

spring security配置文件

spring security的配置文件的内容,spring-security.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd"> <!--spring-security的入门配置--> <!--配置哪些资源不会被拦截 /xxx表示根路径下的某个资源-->
<security:http security="none" pattern="/login.html"/>
<security:http security="none" pattern="/failed.html"/> <security:http auto-config="true" use-expressions="false">
<!-- 配置链接地址,表示任意路径都需要ROLE_USER权限,这里可以配置
一个逗号隔开的角色列表-->
<security:intercept-url pattern="/**" access="ROLE_USER"/> <!--自定义登录页面-->
<security:form-login login-page="/login.html" login-processing-url="/login"
username-parameter="username" password-parameter="password"
authentication-failure-forward-url="/failed.html"
default-target-url="/index.html" />
<!--关闭csrf,默认是开启的-->
<security:csrf disabled="true"/> <!-- 退出 -->
<security:logout invalidate-session="true" logout-url="/logout.do" logout-success-url="/login.html" />
</security:http>
<security:authentication-manager>
<!--配置使用给定的userservice完成认证-->
<security:authentication-provider user-service-ref="userService">
</security:authentication-provider>
</security:authentication-manager> </beans>

在这个配置文件中要注意的是配置用来认证的userService Bean

<!--配置使用给定的userservice完成认证-->
<security:authentication-provider user-service-ref="userService">

创建登录页面和登录失败的页面login.html,failed.html

2.用户认证的实现

新建一个IUserService接口继承UserDetailsService

package com.lyy.service;

import org.springframework.security.core.userdetails.UserDetailsService;

public interface IUserService extends UserDetailsService {

}

实现类如下

@Service("userService")
public class UserServiceImpl implements IUserService { @Autowired
private IUserDao userDao; public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
UserInfo userInfo = userDao.findByUsername(username);
User user=new User(userInfo.getUsername(),"{noop}"+userInfo.getPassword(),getRoles());
return user;
} /*给用户赋值角色信息*/
private List<SimpleGrantedAuthority> getRoles(){
List<SimpleGrantedAuthority> list=new ArrayList<SimpleGrantedAuthority>();
list.add(new SimpleGrantedAuthority("ROLE_USER"));
list.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
return list;
}
}

其中在loadUserByUsername方法中完成查询数据库信息,封装成框架需要的用户信息。

注意 :

UserInfo是封装数据库用户信息的实体类

getRoles用来给用户赋角色信息,spring security认证时用户必须有角色信息,角色信息可以从数据库中查询,在这里直接在代理中写固定值来示意。

用户密码中拼接的"{noop}"字符串是因为我们没有对密码进行加密,所以要告诉框架认证密码时不需要加密。

3.测试

启动工程,访问localhost,会跳转到登录页面,输入数据库中存在的账户和密码就会登录成功并跳转到首页index.html

三、总结

使用数据库完成认证的关键就是实现UserDetailsService接口,并在loadUserByUsername方法中封装一个框架需要的UserDetails对象,即User对象返回给框架,由框架完成后续的认证操作。

同时需要在spring security的配置文件中指定要用来认证的userService 的bean,即实现了loadUserByUsername方法的userService

如果需要查看示例工程的具体代码,可以点击下方的链接在码云上查看

示例工程地址

spring security进阶 使用数据库中的账户和密码认证的更多相关文章

  1. spring security进阶2 添加账户并对账户密码进行加密

    目录 spring security 添加账户并对账户密码进行加密 一.原理分析 1.1加密原理 1.2加密后的登录过程 二.代码实现 2.1添加用户的页面如下, register.html 2.2c ...

  2. Spring Security进阶

    Spring Security进阶 1.连接数据库进行数据的验证 Spring Security进行身份验证或者权限控制时,用户名和密码应该要和数据库的进行比较才行,用户的各种信息我们从数据库中去获取 ...

  3. GitHub https链接中输入账户和密码

    /********************************************************************** * GitHub https链接中输入账户和密码 * 说 ...

  4. (三)spring Security 从数据库中检索用户名和密码

    文章目录 配置 Druid 数据源 数据库 Mapper 文件 自定义 `UserDetailsService` 自定义登陆校验器 `AuthenticationProvider ` 配置 secur ...

  5. Spring Security 入门学习--数据库认证和授权

    首先是使用的SpringBoot框架 基础需要的pom以来如下,基础的springboot项目的创建就不一一赘述了. <!--spring web--> <dependency> ...

  6. Spring Security从后台数据库查询实现登陆控制

    Spring Security框架是一个控制登陆的框架,通过配置文件获取后台的用户名及密码,进行比较进行登陆判断 使用步骤 1.导入依赖 <!-- 身份验证 --> <depende ...

  7. spring boot:spring security用mysql数据库实现RBAC权限管理(spring boot 2.3.1)

    一,用数据库实现权限管理要注意哪些环节? 1,需要生成spring security中user类的派生类,用来保存用户id和昵称等信息, 避免页面上显示用户昵称时需要查数据库 2,如果需要在页面上显示 ...

  8. Spring Security在登录验证中增加额外数据(如验证码)

    在使用Spring Security框架过程中,经常会有这样的需求,即在登录验证时,附带增加额外的数据,如验证码.用户类型等.下面将介绍如何实现. 注:我的工程是在Spring Boot框架基础上的, ...

  9. SpringBoot + Spring Security 学习笔记(三)实现图片验证码认证

    整体实现逻辑 前端在登录页面时,自动从后台获取最新的验证码图片 服务器接收获取生成验证码请求,生成验证码和对应的图片,图片响应回前端,验证码保存一份到服务器的 session 中 前端用户登录时携带当 ...

随机推荐

  1. 《利用Python进行数据分析·第2版》第四章 Numpy基础:数组和矢量计算

    <利用Python进行数据分析·第2版>第四章 Numpy基础:数组和矢量计算 numpy高效处理大数组的数据原因: numpy是在一个连续的内存块中存储数据,独立于其他python内置对 ...

  2. 小白学 Python(9):基础数据结构(列表)(上)

    人生苦短,我选Python 前文传送门 小白学 Python(1):开篇 小白学 Python(2):基础数据类型(上) 小白学 Python(3):基础数据类型(下) 小白学 Python(4):变 ...

  3. 基于docker的mysql8的主从复制

    基于docker的mysql8的主从复制 创建mysql的docker镜像 构建docker镜像,其中数据卷配置内容在下面,结构目录如下 version: '3.7' services: db: # ...

  4. 在非洲运营互联网系统-PAYGo方案

    ​ 尼日利亚当地经济.支付.网络.供电.交通等基建都比较落后,虽然各方面都在缓慢增长,但当地人对高额的刚需产品仍望而却步. 其他非洲国家也有同样的问题. 同理国内,一些低收入人群都想买房,但房价动辄几 ...

  5. 史上最详细的IDEA优雅整合Maven+SSM框架(详细思路+附带源码)

    目录 前言: 1. 搭建整合环境 2.Spring框架代码的编写 3.SpringMVC框架代码的编写 4. Spring整合SpringMVC的框架 5.MyBatis框架代码的编写 6. Spri ...

  6. 函数基础(一)(day10整理)

    目录 昨日内容 文件的基本应用 什么是文件 操作文件的流程 打开文件的三种模式 文件打开的两种方式 绝对路径和相对路径 绝对路径 相对路径 with管理文件上下文 文件的高级应用 新的打开文件的模式 ...

  7. 数据结构(四十四)交换排序(1.冒泡排序(O(n²))2.快速排序(O(nlogn))))

    一.交换排序的定义 利用交换数据元素的位置进行排序的方法称为交换排序.常用的交换排序方法有冒泡排序和快速排序算法.快速排序算法是一种分区交换排序算法. 二.冒泡排序 1.冒泡排序的定义 冒泡排序(Bu ...

  8. Udp 异步通信(三)

    转自:https://blog.csdn.net/zhujunxxxxx/article/details/44258719 1)服务端 using System; using System.Colle ...

  9. fenby C语言 p7

    /*小小加法计算器*/=函数功能说明;(多行) //=注释:(一行) P8 比较 #include <stdio.h>int main(){ int a=10,b=20; if(a< ...

  10. 【XSY2495】余数

    Input Output Input 3 4 Output 4 HINT 原式 =n*m-n除以i向下取整 用数论分块做就可以了 #include<bits/stdc++.h> #defi ...