SpringSecurity之用户名密码登录

标签: Spring Security  SpringSecurity

开始进行实际的Security的代码编写。
Security官方文档
过滤器链:
在这里插入图片描述
目前已有的,后面再加也是加在绿色的过滤器链位置。

建表(用户表,用于登录)

CREATE TABLE `account` (
  `id` varchar(32) NOT NULL COMMENT '主键,UUID编码',
  `user_name` varchar(11) DEFAULT NULL COMMENT '用户名(手机号)',
  `password` varchar(64) DEFAULT NULL COMMENT '密码',
  `num` int(1) DEFAULT NULL COMMENT '登陆失败次数(5)',
  `locked` tinyint(1) DEFAULT '1' COMMENT '是否锁定,默认未锁定,0-锁定',
  `enabled` tinyint(1) DEFAULT '1' COMMENT '是否可用,默认可用,0-被删',
  `expired` tinyint(1) DEFAULT '1' COMMENT '是否过期,true未过期,false过期',
  `role` varchar(50) DEFAULT NULL COMMENT '角色',
  `state` char(1) NOT NULL COMMENT '状态值,是否可用',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

注意,user_name字段需要建立索引,否则如果因为某些原因存在两个相同的手机号登录会失败。可以适当地加一些注册时间,修改时间等字段,此表仅作为最初版。使用mybatis-generator自动生成代码。
数据库默认数据:
在这里插入图片描述

自定义实现类实现UserDetailsService接口:

package com.cong.security.service.impl;

import com.cong.security.entity.Account;
import com.cong.security.mapper.AccountMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
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;

/**
 * @Description 自定义用户名密码登录
 * @Author single-聪
 * @Date 2020/1/7 18:42
 * @Version 1.0.1
 **/
@Slf4j
@Service
public class MyUserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private AccountMapper accountMapper;

    @Override
    public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException {
        // 查询用户信息
        Account account = accountMapper.loginByPhone(name);
        log.info("当前登录账户为:[{}]...账户信息为:[{}]", name, account);
        // 需要考虑到account查询为null的情况
        // 用户名,密码,账户状态,权限
        return new User(name, account.getPassword(), account.getEnabled(), account.getExpired(), true,
                account.getLocked(), AuthorityUtils.commaSeparatedStringToAuthorityList(account.getRole()));
    }
}

注意需要整合MyBatis,无非是相关jar包以及一点点配置,本文不赘述。
现在访问任一接口localhost:8001/login/hello,输入18888888888密码123456之后后端报错:
java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"

进入文章开头Security文档,搜索PasswordEncoder,6.9认证章节介绍了解决办法,内存身份验证,JDBC身份认证(采用默认的密码加解密方式),本文使用最后一种解决方式:注入bean:

package com.cong.security.browser;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

/**
 * @Description TODO
 * @Author single-聪
 * @Date 2020/1/7 18:00
 * @Version 1.0.1
 **/
@Configuration
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 使用表单登录进行身份认证
        http.formLogin()
                .and()
                .authorizeRequests()
                .anyRequest() // 任何请求
                .authenticated(); // 需要身份认证
        super.configure(http);
    }
}

此时启动项目访问之后报错:Authentication request failed: org.springframework.security.authentication.BadCredentialsException: 用户名或密码错误,密码匹配失败,所以我们需要先对一个密码进行加密存储仅数据库中,123456对应的加密后的密码为:$2a$10$ccYrukNANQs9FAMcGfivBOpXU5KI/SGgpUUyOn2iL7FugEyG97ss6,自己加密一次即可,每次结果不一样,现在在调用登录接口输入18888888888和123456即可登陆成功并成功调用指定接口获得返回值。

版权声明:本文为single_cong原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/single_cong/article/details/103879485

智能推荐

【c++】模板和模板类

C++是一种“强类型”语言。也就是说,对于一个变量,编译器必须确切知道它是什么类型。但是,这种强类型函数在实现一些简单函数反而更麻烦。例如:求两大数的较大者,应以Max( )函数,我们需要对不同数据类型分别定义不同重载版本来实现: 我们看到,虽然我们可以通过函数重载去实现,但明显存在一些缺点: 1、所有的函数除返回类型外,函数体都相同,代码复用率低; 2、只要新类型出现,我...

[java][事务]tcc事务实战学习过程

学习项目:https://github.com/14251104246/spring-cloud-rest-tcc 下载源码,进入源码目录运行:mvn clean package Docker Compose运行 docker-compose -f infrastructure-compose.yml up -d docker-compose -f basic-ms-compose.yml up ...

[学习记录,]Mybatis入门

环境: Eclipse 2019 Tomcat 9.0 jdk1.8 开搞 首先创建工程 结构如下 导入Jar包 可在mybatis官网下载 http://www.mybatis.cn/82.html 配置文件mybatis-config.xml 事务管理有两种:JDBC和MANAGED JDBC: MANAGED 数据源类型:UNPOOLED、POOLED、JNDI 创建实体类文件User.ja...

运用for语句来判断数组中值得大小

总结: 1将if语句与数组联合起来判断输入中各组中的最大最小值; 2注意:定义的数组数量是躲多少就要输入多少组数据,少输入就无法输出;...

Bridging signals

Bridging signals Time Limit: 1000MSMemory Limit: 10000K Total Submissions: 10926Accepted: 5982 Description 'Oh no, they've done it again', cries the chief designer at the Waferland chip factory. Once ...

猜你喜欢

一天一大 leet

一天一大 leet 题目(难度:困难): 示例 抛砖引玉 官方答案 高手在民间 菜鸡的自白 20200606 题目(难度:困难): 给定一个未排序的整数数组,找出最长连续序列的长度。 要求算法的时间复杂度为 O(n)。 示例 示例 抛砖引玉 要求算法的时间复杂度为 O(n),即限制了只能循环一次; 先对数组排序 循环数组记录后一个元素等于前一个元素+1或者等于前一个元素的数量 满足条件++,不然重...

Tensorflow实现的CNN文本分类

https://blog.csdn.net/somtian/article/details/69359498 原博文, github 在这篇文章中,我们将实现一个类似于Kim Yoon的卷积神经网络语句分类的模型。 本文提出的模型在一系列文本分类任务(如情感分析)中实现了良好的分类性能,并已成为新的文本分类架构的标准基准。 本文假设你已经熟悉了应用于NLP的卷积神经网络的基础知识。 如果没有,建议...

JDBC新手入门教程

开发工具:idea 数据库:mysql jar包:junit-4.10 mysql-connector-java-8.0.18 junit-4.10下载 mysql-connector-java-8.0.18下载 注意1:jdbc的驱动因为使用的是mysql-connector-java-8.0.18,所以为(“com.mysql.cj.jdbc.Driver”),而不是(...

Lua 排序 table.sort

    正如C#中有Array.Sort(),lua中也有自己的排序方法即table.sort(table,function)。     lua中的排序默认是从大到小的排序;     传入一个方法参数,可以使排序从小到大; 打印结果:  ...

SURF算法简述及Python标记SURF特征检测实践

目录 一、SURF算法 1.算法简介 2.SURF与SIFT的具体差异 二、Python代码实践 1.测试环境 2.测试代码 3.核心函数 4.测试结果 一、SURF算法 1.算法简介 SURF(Speeded-Up Robust Features)加速稳健特征,是一种稳健的局部特征点检测和描述算法。 SURF是对SIFT算法的改进,该算子在保持 SIFT 算子优良性能特点的基础上,同时解决了 S...