博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SpringSecurity学习之基于数据库的用户认证
阅读量:6693 次
发布时间:2019-06-25

本文共 6001 字,大约阅读时间需要 20 分钟。

  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
authorities) { super(username, password, authorities); }}
View Code

  在这里定义的类继承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;@Servicepublic class UserService implements UserDetailsService {    @Autowired    private JdbcTemplate jdbcTemplate;    @Override    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {        User.UserBuilder users = User.withDefaultPasswordEncoder();        Map
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
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; }}
View Code

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

  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 **/@EnableWebSecuritypublic 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);    }}
View Code

在这里主要做以下处理:

 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" %>    Title欢迎:${user.username}
加入时间:${user.joinTime}

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

转载于:https://www.cnblogs.com/niechen/p/9163590.html

你可能感兴趣的文章
[译]Chipmunk教程 - 4定义球体body和shapes
查看>>
EasyUI 常规用法
查看>>
PinnedListView分析一
查看>>
selenium webdriver 学习笔记(二)
查看>>
GridView数据绑定控件的模版列时设置显示的格式
查看>>
在SQL SERVER中实现RSA加解密函数(第一版)
查看>>
判断ios或者android
查看>>
C语言中的注释
查看>>
Working with BeforeProperties and AfterProperties on SPItemEventReceiver
查看>>
JavaSE复习(一)继承多态与常用API
查看>>
Which HRV method to use: FFT or Autoregressive?
查看>>
WEB请求流程
查看>>
PHP define() 定义常量
查看>>
php 上传文件名出现乱码
查看>>
Python 日期与时间
查看>>
最好的vim教程莫过于vimtutor
查看>>
谈谈-ListView的优化
查看>>
hdu 4614 Vases and Flowers
查看>>
poj 3261 Milk Patterns
查看>>
lintcode 128哈希函数
查看>>