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简单用过后的一些笔记的主要内容,如果未能解决你的问题,请参考以下文章