SpringSecurity学习之基于数据库的用户认证
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学习之基于数据库的用户认证的更多相关文章
- spring security基于数据库表进行认证
我们从研究org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl.class的源码开始 public class JdbcDaoI ...
- 项目一:第十一天 2、运单waybill快速录入 3、权限demo演示-了解 5、权限模块数据模型 6、基于shiro实现用户认证-登录(重点)
1. easyui DataGrid行编辑功能 2. 运单waybill快速录入 3. 权限demo演示-了解 4. Apache shiro安全框架概述 5. 权限模块数据模型 6. 基于shiro ...
- 5分钟搞懂:基于token的用户认证
https://www.qikegu.com/easy-understanding/880 用户认证 用户认证或者说用户登录是确认某人确实是某人的过程,生活中靠身份证,网络上就要靠账号和密码.用户提供 ...
- Laravel 5 中使用 JWT(Json Web Token) 实现基于API的用户认证
在JavaScript前端技术大行其道的今天,我们通常只需在后台构建API提供给前端调用,并且后端仅仅设计为给前端移动App调用.用户认证是Web应用的重要组成部分,基于API的用户认证有两个最佳解决 ...
- Linux下基于LDAP统一用户认证的研究
Linux下基于LDAP统一用户认证的研究 本文出自 "李晨光原创技术博客" 博客,谢绝转载!
- JWT 实现基于API的用户认证
基于 JWT-Auth 实现 API 验证 如果想要了解其生成Token的算法原理,请自行查阅相关资料 需要提及的几点: 使用session存在的问题: session和cookie是为了解决http ...
- Spring Security笔记:使用数据库进行用户认证(form login using database)
在前一节,学习了如何自定义登录页,但是用户名.密码仍然是配置在xml中的,这样显然太非主流,本节将学习如何把用户名/密码/角色存储在db中,通过db来实现用户认证 一.项目结构 与前面的示例相比,因为 ...
- Docker Mongo数据库开启用户认证
一.启动mongo容器的几种方式 #简化版 docker run --name mongo1 -p 21117:27017 -d mongo --noprealloc --smallfiles #自定 ...
- springSecurity + jwt + redis 前后端分离用户认证和授权
记录一下使用springSecurity搭建用户认证和授权的代码... 技术栈使用springSecurity + redis + JWT + mybatisPlus 部分代码来自:https://b ...
随机推荐
- java项目显示红叉,程序却没有错误
转 http://blog.sina.com.cn/s/blog_825b7d7c0102w7rq.html (2016-07-02 11:38:38) 分类: javaWeb 电脑换了不同版本的 ...
- (转)什么是.NET?什么是CLI?什么是CLR?IL是什么?JIT是什么,它是如何工作的?GC是什么,简述一下GC的工作方式?
转自:http://www.cnblogs.com/haofaner/articles/2288968.html 1:什么是.NET? NET 是 Microsoft 的用以创建 XML Web 服务 ...
- concurrent.future
concurrent.future module provides a high-level interface for asynchronously executing callables. Bas ...
- java通过poi编写excel文件
public String writeExcel(List<MedicalWhiteList> MedicalWhiteList) { if(MedicalWhiteList == nul ...
- spfa负环判断
正常spfa中加入time数组,循环判断一个点是否入队并更新了n次以上注意是 > n!!其余的没有什么问题 扩展的还有,寻找所有负环上的点,这个可以在spfa中time 发现负环的时候,对那个点 ...
- SRM481
250pt 题意:上帝知道一个“先有鸡还是先有蛋”的答案,上帝和N<=10^6个人说了答案,不过有x个人故意告诉了他们错误的答案,然后有一个人问了这N个人问题的答案,有M个人说先有鸡,N-M个人 ...
- CSS 基础 例子 图片拼合技术
利用background-position xpos ypos 就是以图片的左上角顶点为原点,往下和右都为正,反之为负,移动图片 如: background-position: 15px 20px;( ...
- SET FOREIGN_KEY_CHECKS=0;在Mysql中取消外键约束
Mysql中如果表和表之间建立的外键约束,则无法删除表及修改表结构. 解决方法是在Mysql中取消外键约束: SET FOREIGN_KEY_CHECKS=0; 然后将原来表的数据导 ...
- UNIGUI上传文件
UNIGUI上传文件 uniGUI提供了一个文件上传控件TUniFileUpload,进行数据的导入就变得比较容易.首先将TUniFileUpload控件放置在窗体上,按下导入按钮后,执行TUniFi ...
- ClientDataSet 心得
1. 与TTable.TQuery一样,TClientDataSet也是从TDataSet继承下来的,它通常用于多层体系结构的客户端.很多数据库应用程序都用了BDE,BDE往往给发布带来很大的不便 ...