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. Arduino学习笔记⑥ 硬件串口通信

    1.前言     Ardunio与计算机通信最常用的方式就是串口通信.在Arduino控制器上,串口都是位于Rx和Tx两个引脚,Arduino的USB口通过一个转换芯片与这两个串口引脚连接.该转换芯片 ...

  2. 【redis】redis的过期策略

    redis过期策略 在使用redis做缓存的时候,我们常常会设置过期时间.那么redis是如何清理这些过期的数据呢? 答案是: 定期删除 + 惰性删除 定期删除: redis每100ms就会随机抽查删 ...

  3. web常用知识

    Html 1.打电话,发短信和发邮件 <a href="tel:0755-10086">打电话给:0755-10086</a> <a href=&qu ...

  4. PHP JSON乱码简洁的解决办法

    PHP JSON乱码简洁的解决办法 $arr = array('ret'=>400, 'msg'=>'服务器地址不允许', 'data'=>''); foreach ( $arr a ...

  5. Html.CSS.JavaScript 学习经验

    HTML里面 不要使用 document.getElementsByName() 来获取 元素,会出错. 使用 document.getElementById()更好一些. substring()首字 ...

  6. C++ 11标准

    C++11,也称为C++0x.为目前C++编程语言的最新正式标准(ISO/IEC 14882:2011).它将取代第二版标准ISO/IEC 14882:2003(第一版ISO/IEC 14882:19 ...

  7. Springboot与任务整合(四)

    一 异步任务 启动类 @MapperScan("com.topcheer.*.*.dao") @SpringBootApplication @EnableCaching @Enab ...

  8. Flask源码分析二:路由内部实现原理

    前言 Flask是目前为止我最喜欢的一个Python Web框架了,为了更好的掌握其内部实现机制,这两天准备学习下Flask的源码,将由浅入深跟大家分享下,其中Flask版本为1.1.1. 上次了解了 ...

  9. shell 脚本中的注释详解

    上次写了shell脚本的注释,没想到那么多人的需要,也存在不少不足.这次做个补充吧. 单行注释: 单行注释就比较简单了,直接在行最前端加上符号 # 即可.具体用法如下所示: # this is com ...

  10. 转:NFS原理详解

    原文:http://atong.blog.51cto.com/2393905/1343950 一.NFS介绍 1)什么是NFS 它的主要功能是通过网络让不同的机器系统之间可以彼此共享文件和目录.NFS ...