SpringSecurity给我们提供了一套最基本的认证方式,可是这种方式远远不能满足大多数系统的需求。不过好在SpringSecurity给我们预留了许多可扩展的接口给我们,我们可以基于这些接口实现自己的认证方式。

一、前期准备工作

1.1、创建示例数据库

Student表:

create table student
(
id int auto_increment
primary key,
stuName varchar(8) null,
password varchar(16) null,
joinTime datetime null,
clz_id int null
)
;

Classes(班级)表:

create table classes
(
id int auto_increment
primary key,
clz_name varchar(16) not null
)
;

1.2、添加相关依赖

compile group: 'mysql', name: 'mysql-connector-java'
compile group: 'org.springframework.security', name: 'spring-security-taglibs'
compile('org.springframework.boot:spring-boot-starter-jdbc')

二、实现步骤

2.1  定义Student类

package com.bdqn.lyrk.security.study.app.pojo;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User; import java.sql.Timestamp;
import java.util.Collection; public class Student extends User { private Timestamp joinTime; public Timestamp getJoinTime() {
return joinTime;
} public void setJoinTime(Timestamp joinTime) {
this.joinTime = joinTime;
} public Student(String username, String password, Collection<? extends GrantedAuthority> authorities) {
super(username, password, authorities);
} }

  在这里定义的类继承User,User是SpringSecurity里的一个类,用以描述一个用户和其最基本的属性,当然我们要扩展它的用户我们也可以实现UserDetails接口

2.2 实现UserDetailsService

package com.bdqn.lyrk.security.study.app.service;

import com.bdqn.lyrk.security.study.app.pojo.Student;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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 java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.Map; @Service
public class UserService implements UserDetailsService { @Autowired
private JdbcTemplate jdbcTemplate; @Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User.UserBuilder users = User.withDefaultPasswordEncoder();
Map<String, Object> map = jdbcTemplate.queryForMap("select t.clz_name,t1.stuName,t1.password,t1.joinTime from student t1 inner join classes t on t.id = t1.clz_id where stuName = ?", username);
Timestamp joinTime = null;
if (map != null && map.size() > 0) {
String stuName = (String) map.get("stuName");
String password = (String) map.get("password");
joinTime = (Timestamp) map.get("joinTime");
String clzName = (String) map.get("clz_name");
users.password(password);
users.username(stuName);
SimpleGrantedAuthority authority = new SimpleGrantedAuthority(clzName);
List<GrantedAuthority> list = new ArrayList<>();
list.add(authority);
users.authorities(list);
}
UserDetails userDetails = users.build();
Student student = new Student(userDetails.getUsername(), userDetails.getPassword(), userDetails.getAuthorities());
// UserDetails userDetails = User.withDefaultPasswordEncoder().
student.setJoinTime(joinTime);
return student;
}
}

  在这个接口里我们要实现根据用户名查找用户的方法,那么一般情况下我们都会根据自己系统的用户表来获取用户信息,这里面注意几个方面:

  1)需要设置PasswordEncoder

  2) 需要设置其角色信息,那么在这里我用班级来表示用户的角色

  3)用户的三个重要属性就是 用户名,密码与权限

  4) 这里的返回值(UserDetails)不能返回null,如果根据用户名找不到对应的用户可以抛出UsernameNotFoundException异常

2.3 改造WebSecurityConfig

package com.bdqn.lyrk.security.study.app.config;

import com.bdqn.lyrk.security.study.app.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
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; /**
* spring-security的相关配置
*
* @author chen.nie
* @date 2018/6/7
**/
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired
private UserService userService; @Override
protected void configure(HttpSecurity http) throws Exception {
/*
1.配置静态资源不进行授权验证
2.登录地址及跳转过后的成功页不需要验证
3.其余均进行授权验证
*/
http.
authorizeRequests().antMatchers("/static/**").permitAll().
and().authorizeRequests().antMatchers("/user/**").hasRole("7022").
and().authorizeRequests().anyRequest().authenticated().
and().formLogin().loginPage("/login").successForwardUrl("/toIndex").permitAll()
.and().logout().logoutUrl("/logout").invalidateHttpSession(true).deleteCookies().permitAll()
;
} @Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//设置自定义userService
auth.userDetailsService(userService);
}
}

在这里主要做以下处理:

 1)针对于/user/**路径的请求需要设置对应的权限

 2) 做用户注销的处理,用户注销时需要销毁session与cookie

 3)配置自定义UserDetailService

2.4、改造index.jsp

<%--
Created by IntelliJ IDEA.
User: chen.nie
Date: 2018/6/8
Time: 上午9:56
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
<html>
<head>
<title>Title</title>
</head>
<body>
欢迎:${user.username}
<sec:authorize access="hasRole('7022')">
加入时间:${user.joinTime}
</sec:authorize>
<form action="/logout" method="post">
<input type="submit" value="退出" />
<sec:csrfInput/>
</form> </body>
</html>

  在这里面我们使用spring对security标签的支持判断当前用户是否有对应的角色,另外我们在处理登出操作时必须为post提交且有对应的token防止csrf

SpringSecurity学习之基于数据库的用户认证的更多相关文章

  1. spring security基于数据库表进行认证

    我们从研究org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl.class的源码开始 public class JdbcDaoI ...

  2. 项目一:第十一天 2、运单waybill快速录入 3、权限demo演示-了解 5、权限模块数据模型 6、基于shiro实现用户认证-登录(重点)

    1. easyui DataGrid行编辑功能 2. 运单waybill快速录入 3. 权限demo演示-了解 4. Apache shiro安全框架概述 5. 权限模块数据模型 6. 基于shiro ...

  3. 5分钟搞懂:基于token的用户认证

    https://www.qikegu.com/easy-understanding/880 用户认证 用户认证或者说用户登录是确认某人确实是某人的过程,生活中靠身份证,网络上就要靠账号和密码.用户提供 ...

  4. Laravel 5 中使用 JWT(Json Web Token) 实现基于API的用户认证

    在JavaScript前端技术大行其道的今天,我们通常只需在后台构建API提供给前端调用,并且后端仅仅设计为给前端移动App调用.用户认证是Web应用的重要组成部分,基于API的用户认证有两个最佳解决 ...

  5. Linux下基于LDAP统一用户认证的研究

    Linux下基于LDAP统一用户认证的研究                   本文出自 "李晨光原创技术博客" 博客,谢绝转载!

  6. JWT 实现基于API的用户认证

    基于 JWT-Auth 实现 API 验证 如果想要了解其生成Token的算法原理,请自行查阅相关资料 需要提及的几点: 使用session存在的问题: session和cookie是为了解决http ...

  7. Spring Security笔记:使用数据库进行用户认证(form login using database)

    在前一节,学习了如何自定义登录页,但是用户名.密码仍然是配置在xml中的,这样显然太非主流,本节将学习如何把用户名/密码/角色存储在db中,通过db来实现用户认证 一.项目结构 与前面的示例相比,因为 ...

  8. Docker Mongo数据库开启用户认证

    一.启动mongo容器的几种方式 #简化版 docker run --name mongo1 -p 21117:27017 -d mongo --noprealloc --smallfiles #自定 ...

  9. springSecurity + jwt + redis 前后端分离用户认证和授权

    记录一下使用springSecurity搭建用户认证和授权的代码... 技术栈使用springSecurity + redis + JWT + mybatisPlus 部分代码来自:https://b ...

随机推荐

  1. java 冒泡排序 二分查找 选择排序 插入排序

    下面这个程序是先定义一个整型数组,然后将其中的元素反序赋值,再用冒泡排序进行排序以后用二分查找来查找其中是否有某个数,返回值为-1时表示这个数可能小于这个数组的最小值或大小这个数组的最大值,-2表示这 ...

  2. hibernate之查询

    Query对象 方便的对数据库和持久化对象进行查询,两种表达方式:HQL和SQL; Query经常用来绑定查询参数,限制查询条数.并最终执行查询语句. HQL 查询一个简单类(查询所有) @Test ...

  3. spring启动component-scan类扫描加载,以及@Resource,postConstruct等等注解的解析生效源码

    spring里IOC的原理就不详细写了, 如果想要搞清楚自动扫描组件是如何实现的,还有@Resouce @PostConstruct等注解的工作原理,最好可以先搞清楚整个IOC容器的运作原理再来分析这 ...

  4. hdu 5058 set应用

    http://acm.hdu.edu.cn/showproblem.php?pid=5058 set应用 水题 #include <cstdio> #include <cstdlib ...

  5. execl 导入

    /** * 导入Excel功能   是把execl表中的数据添加到数据表中 */ public function import(){ if (!empty($_FILES)) { $file = re ...

  6. 用命令行上传本地代码到GitHub

    有两种方式上传,ssh和https,ssh老是报错=.=我用的是https 先下载git   https://git-scm.com/downloads 在代码的文件夹的同级目录中邮件打开git ba ...

  7. CSS 基础 例子 行高line-height

    “行高“指一行文字的高度,具体来说是指两行文子间基线间的距离.在CSS,line-height被用来控制行与行之间的垂直距离.line-height 属性会影响行框的布局.在应用到一个块级元素时,它定 ...

  8. javascript Object.create()究竟发生了什么

      这是我在博客园的第一篇博客,早上看了一个大牛的博客,关于javascript继承的,对于大牛使用Object.create()实现继承的方式觉得点问题,就自己研究了一下,所以就有了这篇帖子. 本帖 ...

  9. Java-动态代理技术

    1.程序中的代理 为具有相同接口的目标类的各个方法,添加一些系统功能,如日志,异常处理,计算方法运行的 时间,事务管理等等,都可以交给另一个类去实现这些功能,该类称为代理类. 注意:为了让代理类共享目 ...

  10. tensorflow 安装命令

    sudo pip install --upgrade --ignore-installed six tensorflow-0.9.0-py2-none-any.whl