SpringSecurity-(四)登录用户认证和获取当前用户信息

本文最后更新于:February 4, 2022 pm

Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转、依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。

目录

1.写配置类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package com.tothefor.config;


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

@EnableWebSecurity
public class SecutityConfigTest extends WebSecurityConfigurerAdapter{

@Autowired
private UserDetailsService userDetailsService;

//授权
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/").permitAll() //允许所有人访问,是hasAnyRole
.antMatchers("/div1/**").hasRole("div1") //只有角色是div1的才能访问/div1下的所有页面,下同
.antMatchers("/div2/**").hasRole("div2")
.antMatchers("/div3/**").hasRole("div3");

http.csrf().disable();
http.formLogin().loginPage("/toLogin").usernameParameter("user").passwordParameter("pwd");
http.logout().logoutSuccessUrl("/");
}

//认证
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}

@Bean
PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}

2.实现UserDetailsService

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package com.tothefor.service;

import com.tothefor.dao.PersonMapper;
import com.tothefor.entity.Person;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
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.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

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

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

@Autowired
private PersonMapper personMapper;

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


Person p = personMapper.queryByName(username); //根据用户名查找用户,并返回用户数据
if(p==null){ //没有该用户
throw new UsernameNotFoundException("用户名不存在");
}

String urole = "admin"; //根据数据库查询到的权限
urole="ROLE_"+urole; //因为Security中的角色(有前缀ROLE_)和权限是有区别的
GrantedAuthority g = new SimpleGrantedAuthority(urole); //进行授权

//用来存储用户的权限集
List<GrantedAuthority> auths = new ArrayList<>();
auths.add(g);


return new User(p.getName(),new BCryptPasswordEncoder().encode(p.getPassword()),auths);
}
}

@Service(“UserDetailsService”)中的UserDetailsService是自己写的那个类,是实现了UserDetailsService接口的自定义类。

  • auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());是根据提供的User对象(SpringSecurity中的)中的信息来进行验证。而这个User对象(SpringSecurity中的)的实现类是通过实现UserDetailsService接口实现的,该实现类中就返回了一个User对象(SpringSecurity中的)。
  • 自定义的实现类中重新一个方法loadUserByUsername(String username),根据提供的用户名它去查出用户的具体信息,然后返回一个User对象(SpringSecurity中的User对象),这个User对象会携带着需要验证的信息去验证。

总结

总得来说分为两步。

    1. 还是和原来一样进行配置类的设置,即继承WebSecurityConfigurerAdapter类。只是原来是直接写死用户和密码、角色。现在就不写死,而是通过Security自带的一个User类进行验证。我们需要做的就是把信息放进User类中,然后把这个User对象进行验证。
    1. 编写MyUserDetailsService,是实现的UserDetailsService接口。重写一个方法,此方法可以通过前端获取的用户名进行查询,然后把信息封装成一个User对象返回。

获取当前登录用户信息

此方法与Security无关,只是记录一下有这种方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.tothefor.controller;

import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

import javax.servlet.http.HttpServletRequest;

@Controller
public class TestGet {

@GetMapping("/testGet")
public void getT(HttpServletRequest request){
System.out.println(request.getClass());
System.out.println("当前用户名 "+request.getRemoteUser());
System.out.println("当前用户是否具有某个角色 "+ request.isUserInRole("admin"));

Authentication auth = (Authentication) request.getUserPrincipal();
System.out.println("用户对象 "+request.getUserPrincipal());
System.out.println("用户名 "+auth.getName());
System.out.println("用户权限 "+auth.getAuthorities());
}
}