Spring Boot+Vue项目 微博系统(7):配置Spring Security实现登录

系列目录

Spring Boot+Vue项目 微博系统

UserDetailsService实现类

security 包下新建一个service 包,新建 UserDetailsServiceImpl类,实现UserDetailsService接口:

@Service("UserDetailsServiceImpl")
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private UserService userService;

    @Override
    public UserDetails loadUserByUsername(String s) {
    
        User user = userService.findByUsername(s);
        if (user == null) {
            throw new UsernameNotFoundException("找不到该用户");
        }
        return null;
    }
}

这里有一点,该方法的返回类型是 UserDetails,这是Spring Security内置的一个接口,顾名思义是包含用户信息的东西。这里也可以理解,虽然我们能通过自定义实现loadUserByUsername 方法,但是返回值怎么确定呢?不同的应用可能有不同的用户定义,那怎么才能适配到Spring Security中呢?UserDetails接口就是用来屏蔽具体的用户实现细节的。所以我们还需要实现一下这个接口。

UserDetails实现类

security 包下新建一个entity 包,新建 MyUserDetails类,实现UserDetails接口:

package cn.novalue.blog.security.entity;

import cn.novalue.blog.model.entity.User;
import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.Collection;

@Data
public class MyUserDetails implements UserDetails {

    private User user;
    private Collection <? extends GrantedAuthority> authorities;

    public MyUserDetails(User user) {
        this.user = user;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return authorities;
    }

    @Override
    public String getPassword() {
        return user.getPassword();
    }

    @Override
    public String getUsername() {
        return user.getUsername();
    }

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

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

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

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

可以看到该接口包含很多方法,比如该用户所拥有的权限集合,账户是否锁定、是否过期、是否可用等等,我们可以根据自己的需求对权限做更加细粒度的控制,这里先不管那么多,全返回true

此外将我们自定义的User类以私有字段方式保存在该类中,并重写 getUsernamegetPassword方法,让其返回User中的内容,权限集合暂时只设置个空集合。

修改 UserDetailsServiceImpl

@Service("UserDetailsServiceImpl")
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private UserService userService;

    @Override
    public UserDetails loadUserByUsername(String s) {
    
        User user = userService.findByUsername(s);
        if (user == null) {
            throw new UsernameNotFoundException("找不到该用户");
        }
        MyUserDetails userDetails = new MyUserDetails(user);
        // 先不设置权限信息
        userDetails.setAuthorities(null);

        return userDetails;
    }
}

接下来只需要将我们编写的service配置到Spring Security即可。

Spring Security配置

修改之前SecurityConfig的代码:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    @Qualifier("UserDetailsServiceImpl")
    private UserDetailsService userDetailsService;

    public SecurityConfig() {
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    	// 注入自定义的service
        auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
    	// 禁用csrf
        http.csrf().disable()
        		// 表单登录
                .formLogin()
                // 允许所有请求访问
                .permitAll()
                .and()
                // 其他所有请求都需要认证
                .authorizeRequests()
                .anyRequest()
                .authenticated();

    }

测试登录

启动后端项目,访问localhost:8080/login ,会访问到Spring Security默认的登录页面
在这里插入图片描述

输入用户名密码:“zhangsan” “zhangsan”,提交。会返回到根目录:
在这里插入图片描述

这只是因为我们没有写页面,其实是登录成功的,可以对比输入错误的用户名密码,输出如下:
在这里插入图片描述

配置注销和记住我功能

到此我们看似实现了让Spring Security读取自己的数据库来做登录操作。我们主要做的仅仅是重写了一个方法(loadUserByUsername),并对既有配置做了一些自定义设置。当然这并不完善,但是其它的操作也都与此类似。比如可以很简单地再配置上注销和记住我功能(其实就是我们常见的登录页面中的下次自动登录或者记住密码之类,勾选后登录状态会保持一段时间,不用每次访问页面都要登录):

    @Override
    protected void configure(HttpSecurity http) throws Exception {
    	// 禁用csrf
        http.csrf().disable()
        		// 表单登录
                .formLogin()
                // 允许所有请求访问
                .permitAll()
                .and()
                .logout()
                .permitAll()
                .and()
                .rememberMe()
                .and()
                // 其他所有请求都需要认证
                .authorizeRequests()
                .anyRequest()
                .authenticated();

    }

这里同样可以按照前边的思路,去分析注销和记住我是怎么实现的,其实都是差不多的流程。

这里记住我功能是用的默认配置,也可以使用基于数据库的方式。下一篇就从源码上来看看该怎么修改记住我的配置。

上一篇:
Spring Boot+Vue项目 微博系统(6):登录功能后端实现之新建用户表,测试访问数据库

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值