首页 > 其他分享 >SpringSecurity表单认证(二)

SpringSecurity表单认证(二)

时间:2024-01-16 14:35:16浏览次数:23  
标签:SpringSecurity String 用户 springframework 认证 private User security 表单

用户名+密码

系统默认登录用户名:user

密码每次服务启动后随机生成密码

用户信息获取原理(数据库获取)

实现该接口,security默认自动生成密码关闭。框架源码:

package org.springframework.security.core.userdetails;

public interface UserDetailsService {
    UserDetails loadUserByUsername(String var1) throws UsernameNotFoundException;
}

获取用户信息逻辑,封装在security的UserDetailsService接口,实现该接口只有一个方法UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;

该方法接收用户登陆时的username,根据username可以从数据库,redis,LDAP等读取用户信息,用户信息封装到UserDetails接口的实现类中,实现类User;

框架源码

public class User implements UserDetails, CredentialsContainer {
    private static final long serialVersionUID = 530L;
    private static final Log logger = LogFactory.getLog(User.class);
    private String password;
    private final String username;
    private final Set<GrantedAuthority> authorities;
    private final boolean accountNonExpired;
    private final boolean accountNonLocked;
    private final boolean credentialsNonExpired;
    private final boolean enabled;

User.UserBuilder设置用户名,密码,权限信息返回UserDetails; loadUserByUsername返回UserDetails,security接收并以此来验证访问是否有效.

密码加密解密

框架源码

自定义密码验证(密码加密验证器)

public interface PasswordEncoder {
    String encode(CharSequence rawPassword);//用来加密;原始密码加密后的值,前端传过来的明文密码

    boolean matches(CharSequence rawPassword, String encodedPassword);//加密后的密码与用户上传的密码(明文)是否匹配

    default boolean upgradeEncoding(String encodedPassword) {
        return false;
    }
}

org.springframework.security.crypto.bcrypt;包实现

可自定义实现该接口

实际场景中,用户密码是加密后传输,保存的密码都是加密的

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.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //http.formLogin()  //表单登陆认证方法,浏览器跳转到specurity默认登陆页面
        http.httpBasic()//浏览器弹出登陆对话框登陆认证方式
        .and()
        .authorizeRequests() ////设置请求符合访问资源的权限
        .anyRequest().authenticated(); //对任何请求都要登陆认证后才能访问
    }
    @Bean
    public PasswordEncoder passwordEncoder() {
        //return NoOpPasswordEncoder.getInstance(); //已弃用
        return new BCryptPasswordEncoder();
    }
}

处理用户校验

用户密码校验
@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private PasswordEncoder pw;

    @Resource
    private UserMapper userMapper;

    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        //TODO 查询用户信息(mysql,redis,ldap)
        User user = userMapper.selectOne(Wrappers.lambdaQuery(User.class).eq(User::getName, s));
        if (user == null) {
            throw new UsernameNotFoundException("用户不存在");
        }
        String pwd = pw.encode(user.getPasswd());
    //TODO 从数据库获取用户相关权限
        String[] authorities = {"admin", "test"};//在configure方法中设置验证权限
        UserDetails userDetails = org.springframework.security.core.userdetails.User.withUsername(user.getName()).password(pwd).authorities(authorities).build();
        return userDetails;
    }
}

设置用户帐户过期校验

实现UserDetailsService接口的User类的boolean isAccountNonExpired()方法。

根据数据库表中设计来设定用户过期时间。

如果当前时间大于过期时间,说明用户已过期,设置User.UserBuilder.accountExpired(true),默认为false

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private PasswordEncoder pw;

    @Resource
    private UserMapper userMapper;

    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        //TODO 查询用户信息(mysql,redis,ldap)
        User user = userMapper.selectOne(Wrappers.lambdaQuery(User.class).eq(User::getName, s));
        if (user == null) {
            throw new UsernameNotFoundException("用户不存在");
        }
        String pwd = pw.encode(user.getPasswd());
        //TODO 从数据库获取用户相关权限
        String[] authorities = {"admin", "test"}; //在configure方法中设置验证权限
        org.springframework.security.core.userdetails.User.UserBuilder builder = org.springframework.security.core.userdetails.User.withUsername(user.getName()).password(pwd).authorities(authorities);
        //查询用户的信息中created表示为过期时间,判断created是否小于当前时间
        Long currentTime = LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
        Long expireTime = user.getCreated().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
        if (currentTime>expireTime){
            builder.accountExpired(true);
        }
        //UserDetails userDetails = org.springframework.security.core.userdetails.User.withUsername(user.getName()).password(pwd).authorities(authorities).build();
        UserDetails userDetails = builder.build();
        return userDetails;
    }
设置用户密码过期校验

与设置用户帐户过期校验逻辑一样,默认为false

User.UserBuilder.credentialsExpired(true);

设置用户锁定校验

与设置用户帐户过期校验逻辑一样,默认为false

User.UserBuilder accountLocked(true)

设置用户是否可用校验

User.UserBuilder disabled(true)

校验总结

boolean isAccountNonExpired();
boolean isAccountNonLocked();
boolean isCredentialsNonExpired();
boolean isEnabled();

User类对这四个方法的实现只是返回false或true,判断逻辑是自己判断出结果,通过调置User的属性值是false或true,在由这几个方法返回;

自己可实现UserDetails接口,将逻辑判断直接写入这几个方法中。

登陆成功,客户端将JSESSIONID保存在Cookie里,每次请求携带

"Cookie": "JSESSIONID=1C6C3BD094405290E5802CB98F627E19"

标签:SpringSecurity,String,用户,springframework,认证,private,User,security,表单
From: https://www.cnblogs.com/wangzhilei-src/p/17967576

相关文章

  • 处理HTTP请求中的表单数据
    处理HTTP请求中的表单数据是Web开发中常见的任务。在Go语言中,可以使用net/http包来解析HTTP请求中的表单数据。首先,确保你已经创建了一个HTTP服务器,并且能够接收和处理POST请求。然后,你可以使用r.ParseForm()函数来解析请求中的表单数据。以下是一个简单的示例,演示了如何处理HTTP请......
  • 认证授权JWT
    JWT1、从JWT的全称可以看出,JWT本身也是Token,一种规范化之后的JSON结构的Token。JWT自身包含了身份验证所需要的所有信息,因此,我们的服务器不需要存储Session信息。这显然增加了系统的可用性和伸缩性,大大减轻了服务端的压力(因为session还需要保存,但是jwt只要签名验证......
  • 3C认证项目认证申请资料 CCC认证流程
    3C认证项目认证申请资料:1、强制性产品认证申请书。2、申请人的《企业法人营业执照》或登记注册证明复印件(初次申请或变更时提供);3、生产厂的组织结构图(初次申请或变更时提供);4、申请认证产品工艺流程图(初次申请或变更时提供);5、例行检验用关键仪器设备(见认证实施规则工厂质量控制检......
  • 电子产品出口欧盟如何办理CE认证
    欧盟CE认证办理流程:申请(1.填写申请表2.提供资料并寄样);报价(根据您提供的资料会有工程师来拟定相应的标准,测试时间及相应费用);付款(申请人确认报价后,签订立案申请表及服务协议并支付款项);测试(实验室根据相关的欧盟检测标准对所申请产品进行全套测试);测试通过,报告完成;项......
  • 蓝牙音响CEC认证办理流程
    一、CEC认证是什么?CEC认证怎么申请,流程是什么?符合了CEC认证的要求,产品才能在美国加利福尼亚州销售与流通,不然产品是无法在美国加利福尼亚州正常流通与销售的。CEC认证是美国加利福尼亚州能效认证,蓝牙音响做为一款需要依靠内置锂电池来供电的电子产品,它在CEC认证标准中属于smallbatt......
  • Django rest_framework用户认证和权限
    完整的代码https://gitee.com/mom925/django-system使用jwt实现用户认证pipinstalldjangorestframework-simplejwt重新定义一下User类classUsers(AbstractUser):classMeta:db_table="system_users"verbose_name="用户表"......
  • SpringSecurity表单认证(一)
    配置类创建securityConfig,并继承WebSecurityConfigurerAdapter,它是web应用的安全适配器重写configure方法,共有三个,重写参数为http的configure方法configure(HttpSecurityhttp)方法,配置表单登陆认证方法,任何请求都需要表单认证@Overrideprotectedvoidconfigure(HttpSe......
  • 喜报!思迈特荣获DCMM稳健级认证,数据管理能力达国家标准
    近日,经中国电子信息行业联合组织主办的数据管理能力成熟度评估(简称DCMM)专家评审会的严格审查,思迈特成功取得DCMM稳健级(乙方三级)证书。这一成就标志着在数据战略和执行方面,思迈特取得了显著的进展,其数据管理能力已达到行业领先水平。DCMM是我国数据管理领域的国家级评估标准,自2018年......
  • 聊城申请ISO认证包含了哪些内容有什么好处
    聊城申请ISO认证包含了哪些内容有什么好处恒标知产刘经理 什么是ISO?ISO是世界上最大的国际标准化组织(InternationalOrganizationforStandardization)的简称。它成立于1947年2月23日,它的前身是1928年成立的“国际标准化协会国际联合会”(简称ISA)。ISO的成员由来自世界上100多个......
  • 每日一练 | 华为认证真题练习Day164
    1、当两台BGP邻居协商的HOLDTime参数为0时,则不发送Keeplive报文。A.正确B.错误2、ospf路由协议中,bandwidth-reference命令的单位是mbps。A.正确B.错误3、在OSPF广播或者NBMA网络类型中,ROUTERPRIORITY大的设备不一定会成为DR。A.正确B.错误4、在广播或nbma网络上,并非所有的......