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即可登陆成功并成功调用指定接口获得返回值。

发布了43 篇原创文章 · 获赞 25 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/single_cong/article/details/103879485