SpringSecurity使用自定义登入服务

本文详细介绍了在Spring Security框架中,如何自定义UserDetails和UserDetailsService实现类,以及如何配置Security,实现基于数据库的用户认证和权限管理。通过具体代码示例,展示了如何从数据库获取用户信息并封装为UserDetails,以及如何设置特定页面的访问权限。

1. 自定义UserDetails实现类

package com.druisecurity.demo.Pojo;

import lombok.Data;
import lombok.Getter;
import lombok.ToString;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;

import java.util.Collection;

/**
 * 自定义返回session中的UserDetail对象,带上userid值
 */
@Getter  // 属性自动生成get方法
@ToString
public class MyUser implements UserDetails {
    // 自定义属性id
    private Integer id;
    // UserDetails默认属性
    private String username;
    private String password;
    private Collection<GrantedAuthority> authorities;
    
    public MyUser(){
    }
	// 构造方法属性注入
    public MyUser(String username, String password, Integer id, Collection<GrantedAuthority> authorities) {
        this.authorities = authorities;
        this.password = password;
        this.username = username;
        this.id = id;
    }
	
	// 以下为默认接口方法
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return authorities;
    }

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

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

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

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

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

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

2. 自定义UserDetailService实现类

package com.druisecurity.demo.config;

import com.druisecurity.demo.Dao.Mapper;
import com.druisecurity.demo.Pojo.MyUser;
import com.druisecurity.demo.Pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * 继承UserDetailsService接口
 */
@Service
public class MyUserService implements UserDetailsService {

    @Autowired
    Mapper mapper; // 操作数据库
    @Autowired
    PasswordEncoder passwordEncoder;  // 引入加密方式
	
	// 实现接口方法
    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {

        // 从数据库查询用户对象
        User user = mapper.selectUserOne(s);
        // 定义UserDetails
        MyUser userDetails = null;
        if (user !=null){
            System.out.println(user.getPwd());
            // 创建数组,用于存放用户权限
            List<GrantedAuthority> authorities = new ArrayList<>();
            // 加入用户权限
            authorities.add(new SimpleGrantedAuthority("ROLE_"+user.getRole()));
            authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
            // 密码需要使用密码加密
            // 返回自定义的UserDetail对象
            userDetails = new MyUser(user.getUsername(),passwordEncoder.encode(user.getPwd()),user.getId(),authorities);

        }
        return userDetails;
    }
}

3. 自定义security配置

package com.druisecurity.demo.config;

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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    MyUserService myUserService;  // 自动注入MyUserService 

    @Override   // 认证
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 使用自定义的登入业务和默认密码编译格式(没设置编译格式会报错)
        auth.userDetailsService(myUserService).passwordEncoder(passwordEncoder());
    }

    @Override   // 授权:为特定网页设置权限,拥有权限的用户才能进行访问此页面
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/").permitAll()  // 任何角色都可以访问根路径,该路径不需要用户进行登入,其他都要
                .antMatchers("/login1","/formlogin","/outlog").permitAll()
                .antMatchers("/hello").hasAuthority("ROLE_ADMIN")
                .antMatchers("/hello1").hasRole("USER")
                .anyRequest().authenticated()                           
        ;
        http.formLogin().loginPage("/login1").loginProcessingUrl("/formlogin");
        http.logout()     // 默认退出路径 /logout
                .logoutRequestMatcher(new AntPathRequestMatcher("/logout","POST")).permitAll()
            .logoutSuccessUrl("/")       // 退出成功后调整至 /
            .invalidateHttpSession(true) // 是否删除session
            .deleteCookies("JSESSIONID") // 删除cookie中JSESSIONID值
        ;

        http.rememberMe(); // 开启记住我功能
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        // BCryptPasswordEncoder:Spring Security 提供的加密工具,可快速实现加密加盐
        return new BCryptPasswordEncoder();
    }
}

4. 结果图
session打印结果

本章参考地址

自定义数据库获取用户信息思路

认证

先说认证,与本次实现密切相关的几个类或接口,是UserDetails、UserDetailsService、AuthenticationProvider,我们可以这么理解:UserDetails是用来封装用户的,用户的帐号信息啊、一些权限啊,帐号状态啊等信息,从数据库那里拿到,首先是要封装成UserDetails的样子,才可以在Spring Security框架中使用的;UserDetailsService,顾名思义,处理UserDetails的Service,它是提供去查询账号信息并封装成UserDetails的服务;AuthenticationProvider的主要工作是负责认证,从登录请求那里拿到帐号密码之类,然后再跟从数据库资源那里得到的UserDetails进行对比确认,如果发现不对劲儿,该报错报错,该提示提示,如果OK,则把这些信息揉巴成一团,封装成一个包含所有信息的认证对象,交给 Spring Security 框架进行管理,供后边有需要的时候随时取用。

授权

接下来说鉴权,Spring Security 的鉴权方式有多种,我们大概捋一下,这里我们重点讲述如何通过自定义过滤器的鉴权方式,来实现数据库配置权限的动态管理,与此密切相关的几个核心类或接口分别是:AbstractSecurityInterceptor(Filter)、FilterInvocationSecurityMetadataSource和AccessDecisionManager。我们可以这么理解,FilterInvocationSecurityMetadataSource是权限资源管理器,它的主要工作就是根据请求的资源(路径),从数据库获取相对应的权限信息;AccessDecisionManager类似权限管理判断器,负责校验当前认证用户的权限,是否可以访问;AbstractSecurityInterceptor就是前边这两个角色负责表演的地方,拿到访问资源所需的权限,和认证用户的权限,对比,出结果,如果出现对比不成功,分分钟抛要一个拒绝访问的异常,403forbidden了! 在这里先把这几个类或者接口,默默的混个眼熟,认证相关:UserDetails、UserDetailsService、AuthenticationProvider;鉴权相关:AbstractSecurityInterceptor(Filter)、FilterInvocationSecurityMetadataSource和AccessDecisionManager,谁是干啥的,谁跟谁什么关系,大概就是那么个意思了,也能猜出 Spring Security 是怎么工作的。 接下来还会介绍下 Spring Security 的核心配置类:WebSecurityConfigurerAdapter,它的主要职责就是配置配置哪些资源不需要权限限制啊,哪些需要啊等等,以及做一些综合性的配置操作,以及 Spring Security 本身的注册等。 以上是 Spring Security 应用的一个概述,目的是有个简单的了解,提前混个眼熟,便于思路连续性的展开。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值