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. 结果图

自定义数据库获取用户信息思路
认证
先说认证,与本次实现密切相关的几个类或接口,是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 应用的一个概述,目的是有个简单的了解,提前混个眼熟,便于思路连续性的展开。

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

被折叠的 条评论
为什么被折叠?



