详解Spring Security进阶身份认证之UserDetailsService(附源码)

    在上一篇Spring Security身份认证博文中,我们采用了配置文件的方式从数据库中读取用户进行登录。虽然该方式的灵活性相较于静态账号密码的方式灵活了许多,但是将数据库的结构暴露在明显的位置上,绝对不是一个明智的做法。本文通过Java代码实现UserDetailsService接口来实现身份认证。


    1.1 UserDetailsService在身份认证中的作用


    Spring Security中进行身份验证的是AuthenticationManager接口,ProviderManager是它的一个默认实现,但它并不用来处理身份认证,而是委托给配置好的AuthenticationProvider,每个AuthenticationProvider会轮流检查身份认证。检查后或者返回Authentication对象或者抛出异常。


    验证身份就是加载响应的UserDetails,看看是否和用户输入的账号、密码、权限等信息匹配。此步骤由实现AuthenticationProvider的DaoAuthenticationProvider(它利用UserDetailsService验证用户名、密码和授权)处理。包含 GrantedAuthority 的 UserDetails对象在构建 Authentication对象时填入数据。


wKiom1TJ_G-QennHAALbrutxzyc077.jpg


    

    1.2 配置UserDetailsService


    1.2.1 更改Spring-Security.xml中身份的方式,使用自定义的UserDetailsService。


<security:authentication-manager>
 <security:authentication-provider user-service-ref="favUserDetailService">
     </security:authentication-provider>
</security:authentication-manager>

<bean id="favUserDetailService" class="com.favccxx.favsecurity.security.FavUserDetailService" />


    

    1.2.2 新建FavUserDetailsService.java,实现UserDetailsService接口。为了降低学习的难度,这里并没有与数据库进行集成,而是采用模拟从数据库中获取用户的方式进行身份验证。示例代码如下:


package com.favccxx.favsecurity.security;

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

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.security.core.GrantedAuthority;
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;

public class FavUserDetailService implements UserDetailsService {

private static final Logger logger = LogManager.getLogger(FavUserDetailService.class);

/**
* 根据用户名获取用户 - 用户的角色、权限等信息
*/
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
UserDetails userDetails = null;
try {
com.favccxx.favsecurity.pojo.User favUser = new com.favccxx.favsecurity.pojo.User();
favUser.setUsername("favccxx");
favUser.setPassword("favccxx");
Collection<GrantedAuthority> authList = getAuthorities();
userDetails = new User(username, favUser.getPassword().toLowerCase(),true,true,true,true,authList);
} catch (Exception e) {
e.printStackTrace();
}


return userDetails;
}

/**
* 获取用户的角色权限,为了降低实验的难度,这里去掉了根据用户名获取角色的步骤
* @param
* @return
*/
private Collection<GrantedAuthority> getAuthorities(){
List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>();  
authList.add(new SimpleGrantedAuthority("ROLE_USER"));
authList.add(new SimpleGrantedAuthority("ROLE_ADMIN"));

return authList;
}



}


    1.2.3 启动应用服务器,只要用户名和密码不全是favccxx,就会产生下面的错误。


wKioL1TJ_giBpILOAAF2QL-ASRg527.jpg


    用户名和密码都输入favccxx,则登陆成功


wKiom1TJ_SexYSkWAAHYMLuVe1E670.jpg


    1.3 跟踪UserDetailsService。


    身份认证的调用流程图如下,用户可下载Spring Security源代码跟踪调试。


wKiom1TJ_WvBCs7aAAHZn6syY1Y174.jpg


    1.4 如不能正常运行,点这里看看源代码吧


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Spring Security中,可以使用UserDetailsService来获取用户信息并进行身份认证UserDetailsService是一个接口,需要自定义实现来提供用户信息。 下面是一个简单的示例,演示如何使用UserDetailsService来进行身份认证: 1. 创建一个实现UserDetailsService接口的类,并实现其loadUserByUsername方法。在该方法中,你可以从数据库或其他数据源中获取用户信息,并返回一个实现了UserDetails接口的用户对象。 ```java @Service public class UserDetailsServiceImpl implements UserDetailsService { @Autowired private UserRepository userRepository; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User user = userRepository.findByUsername(username); if (user == null) { throw new UsernameNotFoundException("User not found with username: " + username); } return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), getAuthorities(user.getRoles())); } private Collection<? extends GrantedAuthority> getAuthorities(Set<Role> roles) { return roles.stream() .map(role -> new SimpleGrantedAuthority(role.getName())) .collect(Collectors.toList()); } } ``` 2. 在配置类(如SecurityConfig)中,使用@Autowired注解将UserDetailsService实例注入,并在configure方法中配置AuthenticationManagerBuilder。 ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsService userDetailsService; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder()); } // ...其他配置... @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } } ``` 上述代码中,我们将UserDetailsService实例注入到AuthenticationManagerBuilder中,并使用BCryptPasswordEncoder作为密码编码器。 3. 在登录过程中,Spring Security将调用UserDetailsService的loadUserByUsername方法来获取用户信息,并使用密码编码器对用户输入的密码进行验证。 现在,当用户尝试进行身份认证时,UserDetailsService将被调用,从数据库中获取用户信息并进行验证。你可以根据自己的需求来自定义UserDetailsService的实现,以适应不同的用户信息存储方式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值