springboot 整合 security(二) 使用数据库账号密码实现登录流程

上篇讲了如何简单实现security功能,但只能使用框架指定的账号密码,不符合我们的应用场景。这篇讲一下如何使用数据库账号密码实现登录流程

首先,还是创建我们的项目

然后是数据库的设计 

然后是用户controller层的代码 UserController.java

@RestController
@RequestMapping("user")
public class UserController {

    @Autowired
    UserService userService;

    @RequestMapping("/list")
    public List<User> list() {
        List<User> list = userService.getList();
        return list;
    }
}

健康检查类controller层的代码 UserController.java

@RestController
@RequestMapping("ok")
public class OkController {

    @RequestMapping("")
    public String ok() {
        System.out.println("security1 ok!");
        return "security1 ok!";
    }
}

security配置文件 WebSecurityConfig.java

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
    /**
     * 需要放行的URL
     */
    private static final String[] AUTH_WHITELIST = {
            "/ok/**"
    };

    // 配置 URL 访问权限
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests() // 开启 HttpSecurity 配置
                .antMatchers(AUTH_WHITELIST).permitAll().anyRequest().authenticated() // 用户访问其它URL都必须认证后访问(登录后访问)
                .and().formLogin() // 开启表单登录
                .and().csrf().disable(); // 关闭csrf
    }
}

来看一下我们的代码结构

 通过user+控制台输出的密码,登录上系统之后,可以看到我们的用户列表信息

接下来,就是我们的主题了。

我们需要建一个MyUserDetailsService类,这个类主要用来往框架中注入账号、密码、角色、是否可用等信息,然后与登录接口传递过来的账号密码进行比对(注意,他会将前端传过来的密码进行加密,所以在我们注入的时候也需要加密,或者数据库直接存储密文)。代码如下。

package com.mu.security2.security;

import com.mu.security2.entity.User;
import com.mu.security2.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

@Component
public class MyUserDetailsService implements UserDetailsService {

    @Autowired
    UserService userService;
    @Autowired
    PasswordEncoder passwordEncoder;

    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {

        System.out.println("进入》》》》MyUserDetailService");
        System.out.println("登陆用户输入的用户名:" + s);

        Map<String, Object> param = new HashMap<>();
        param.put("username", s);
        User user = userService.getUser(param);
        if (user==null){
            throw new UsernameNotFoundException("用户不存在");
        }

        String password = user.getPassword();
        String encode = passwordEncoder.encode(password);
        System.out.println("加密前的密码:"+ password);
        System.out.println("加密后的密码:"+ encode);

        UserVo userDetails = new UserVo();
        userDetails.setUsername(user.getUsername());
        userDetails.setPassword(user.getPassword());
        userDetails.setAccountNonLocked(user.getLocked()==2);
        userDetails.setEnabled(user.getDeleted()==2);
        userDetails.setAccountNonExpired(true);
        userDetails.setCredentialsNonExpired(true);

        return userDetails;
    }

}

对应securityUserDetails的用户类

package com.mu.security2.security;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.Set;

public class UserVo implements UserDetails {

    /**
     * 账号
     */
    private String username;
    /**
     * 密码
     */
    private String password;
    /**
     * 角色信息
     */
    private Set<GrantedAuthority> authorities;
    /**
     * 账户是否未过期
     */
    private boolean accountNonExpired;
    /**
     * 账户是否未锁定
     */
    private boolean accountNonLocked;
    /**
     * 密码是否未过期
     */
    private boolean credentialsNonExpired;
    /**
     * 账户是否可用
     */
    private boolean enabled;

    @Override
    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Override
    public Set<GrantedAuthority> getAuthorities() {
        return authorities;
    }

    public void setAuthorities(Set<GrantedAuthority> authorities) {
        this.authorities = authorities;
    }

    @Override
    public boolean isAccountNonExpired() {
        return accountNonExpired;
    }

    public void setAccountNonExpired(boolean accountNonExpired) {
        this.accountNonExpired = accountNonExpired;
    }

    @Override
    public boolean isAccountNonLocked() {
        return accountNonLocked;
    }

    public void setAccountNonLocked(boolean accountNonLocked) {
        this.accountNonLocked = accountNonLocked;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return credentialsNonExpired;
    }

    public void setCredentialsNonExpired(boolean credentialsNonExpired) {
        this.credentialsNonExpired = credentialsNonExpired;
    }

    @Override
    public boolean isEnabled() {
        return enabled;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }
}

然后是在配置文件中配置我们自己创建的这个类,以及指定加密方式

package com.mu.security2.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    MyUserDetailsService userDetailsService;

    /**
     * 需要放行的URL
     */
    private static final String[] AUTH_WHITELIST = {
            "/ok/**"
    };

    // 配置 URL 访问权限
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests() // 开启 HttpSecurity 配置
                .antMatchers(AUTH_WHITELIST).permitAll().anyRequest().authenticated() // 用户访问其它URL都必须认证后访问(登录后访问)
                .and().formLogin() // 开启表单登录
                .and().csrf().disable(); // 关闭csrf
    }

    // 配置用户及其对应的角色
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
    }

    //指定密码的加密方式
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

我们启动来试一下

控制台没有打印密码,用我们数据库的账号密码来尝试登录

页面显示了Bad credentials,密码错误,看一下控制台 

 原因呢是因为框架会将前端传过来的密码进行加密,然后再与我们注入的账号密码进行比对。因此我们复制控制台打印的加密后的密码到数据库中(建议数据库存储加密后的密码,防止密码泄露问题)。

​​​​​​​

 成功用账号zx密码123登陆啦

源码地址

security: springboot security 整合,简单实现​​​​​​​

附参考博客

基础登录demo

基础介绍​​​​​​​

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值