springsecurity简单用过后的一些笔记

Posted ozx143570

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springsecurity简单用过后的一些笔记相关的知识,希望对你有一定的参考价值。

 

Spring Security认证是由 AuthenticationManager 来管理的,但是真正进行认证的是 AuthenticationManager 中定义的 AuthenticationProvider。AuthenticationManager 中可以定义有多个 AuthenticationProvider。当我们使用 authentication-provider 元素来定义一个 AuthenticationProvider 时,如果没有指定对应关联的 AuthenticationProvider 对象,Spring Security 默认会使用 DaoAuthenticationProvider。DaoAuthenticationProvider 在进行认证的时候需要一个 UserDetailsService 来获取用户的信息 UserDetails,其中包括用户名、密码和所拥有的权限等。所以如果我们需要改变认证的方式,我们可以实现自己的 AuthenticationProvider;如果需要改变认证的用户信息来源,我们可以实现 UserDetailsService。

 

 

1.实现UserDetailsService 接口

CustomUserDetailsService类: 

package cn.lger.security;


import cn.lger.dao.UserDao;
import cn.lger.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
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 java.util.ArrayList;
import java.util.List;

public class CustomUserDetailsService implements UserDetailsService {

    @Autowired
    private  UserDao userDao;
    
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userDao.findByUsername(username);
        if(user == null){
            throw new UsernameNotFoundException("not found");
        }
        List<SimpleGrantedAuthority> authorities = new ArrayList<SimpleGrantedAuthority>();
        authorities.add(new SimpleGrantedAuthority(user.getRole()));
        System.err.println("username is " + username + ", " + user.getRole());
        return new org.springframework.security.core.userdetails.User(user.getUsername(),
                user.getPassword(), authorities);
    }

}

在下面的configure(AuthenticationManagerBuilder auth) 方法中添加这个UserDetailsService 

SecurityConfig类:

package cn.lger.config;

import cn.lger.security.CustomUserDetailsService;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Override
    @Bean
    public UserDetailsService userDetailsService() {
        return new CustomUserDetailsService();
    }


    @Override  
    protected void configure(AuthenticationManagerBuilder auth)  
            throws Exception {  
        auth
                .userDetailsService(userDetailsService())
                .passwordEncoder(new BCryptPasswordEncoder());
    }  
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/", "/home").permitAll()
                .antMatchers("/css/**","/js/**","/img/**","/vendors/**").permitAll()
                .anyRequest().permitAll()
                .and()
            .formLogin()
                .defaultSuccessUrl("/user/list")
                .permitAll()
                .and()
            .logout()
                .permitAll()
                .and()
                .csrf().disable();
    }
  
}

这里虽然是给AuthenticationManagerBuilder这个构造类来添加的UserDetailsService 而不是真正的AuthenticationManager这个类,但是经过我尝试过断点调试,在启动阶段就会进入断点,断点的调试结果如下:

刚开始进入我们自己写的安全配置类SecurityConfig的父类WebSecurityConfigurerAdapter的init(final WebSecurity web)这个方法

技术分享图片

断点的位置会调用getHttp()这个方法,然后我们下一步进入这个方法的内部看看,如下图:

技术分享图片

这里断点位置我已经看到AuthenticationManager这个类的一个对象的构建了,然后继续进入authenticationManager()这个方法内部看看,这个AuthenticationManager对象是如何构建的:

技术分享图片

进来先判断AuthenticationManager这个类是不是已经初始化一个对象了了,如果初始化了就直接返回AuthenticationManager的对象,否则就调用configure(AuthenticationManagerBuilder auth)这个方法,因为SecurityConfig这个类重写了WebSecurityConfigurerAdapter这个类原本的configure(AuthenticationManagerBuilder auth)的这个方法,所以运行到下一个断点会到SecurityConfig类的configure(AuthenticationManagerBuilder auth)方法上:

技术分享图片

这样就在构建AuthenticationManager类的实例前给它提供了一个UserDetailsService实例,这样DaoAuthenticationProvider 就可以通过这个实例里面的loadUserByUsername(String username)(这个方法需要我们自己实现)获取一个UserDetails的实例,并且我实验过,这个loadUserByUsername(String username)方法会在我们登陆认证的时候起作用,若果我们登陆成功就会返回一个UserDetails的实例,这个UserDetails的实例中包含了用户的用户名,密码和权限(权限是一个set,说明可以支持一个用户多个角色)

以上是关于springsecurity简单用过后的一些笔记的主要内容,如果未能解决你的问题,请参考以下文章

Mac装win10过后不能连WiFi了怎么解决?

安卓笔记一

Spring Security 架构原理学习笔记

Apache Shiro学习笔记总结

梦断代码阅读笔记03

VUE&Element简单介绍。