Spring Security OAuth2 密码模式实现统一登录

介绍

Spring Security OAuth2 使用用户名和密码进行授权被称为"密码授权模式"(Password Grant),它允许用户通过直接提供其用户名和密码来获取访问令牌(access token)。这种方式通常用于受信任且高度安全的应用程序,例如原生移动应用程序。

Git地址:yunfeng-boot3-sercurity: Spring Security OAuth2 统一登录(密码模式)

版本

SpringBoot 2.5.6

其他参考

这个是关于Spring Security OAuth2授权码模式的参考,非常简单,易于理解。

重要角色
  • AuthenticationManager:顶级认证管理器
  • ProviderManager:是AuthenticationManager实现类,管理和执行一组认证提供者(AuthenticationProvider).
  • AuthenticationProvider: 认证提供者,执行身份验证的操作。通过实现其中的 authenticate(Authentication authentication) 方法,你可以自定义身份验证逻辑。
  • UserDetailsService: 用户详细信息服务。 通过实现其接口,可以从数据库加载用户信息,并返回一个UserDetails对象。
  • UsernamePasswordAuthenticationFilter 是 Spring Security 提供的一个过滤器,用于处理基于用户名和密码的身份验证请求
核心流程
  • UsernamePasswordAuthenticationFilter 入口
  • 委托具体的ProviderManager -> 具体的UserDetailsService -> 数据库校验
核心配置

根据以上流程,要实现用户名和密码的校验逻辑,需要配置和实现自定义的认证管理、认证提供者和用户详细信息服务。

  1. 自定义的认证管理器,注入Bean到容器中。
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
  /**
   * password 密码模式需要在认证服务器中设置 中配置AuthenticationManager
   */
  @Bean
  @Override
  public AuthenticationManager authenticationManagerBean() throws Exception {
    return super.authenticationManagerBean();
  }

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

}
  1. 自定义用户详细信息,实现从数据库中获取用户信息
@Service
public class UserDetailsServiceImpl implements UserDetailsService {

  @Resource
  private PasswordEncoder passwordEncoder;

  @Override
  public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
    String password = passwordEncoder.encode("123456");
    System.out.println(password);
    return new User("admin", password,
      AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
  }
}
  1. 把自定义的认证管理器和用户详细信息服务,配置到认证服务适配器的端点设置中。
/**
   * 该方法用于配置授权服务器的端点(endpoints)。你可以设置令牌存储方式、指定认证管理器、用户详细信息服务、令牌生成和解析的方式等。
   */
  @Override
  public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    RedisTokenStore tokenStore = new RedisTokenStore(redisConnectionFactory);
    tokenStore.setPrefix(TOKEN_STORE_PREFIX);
    endpoints.tokenStore(tokenStore)
      .authenticationManager(authenticationManager) //配置认证管理器
      .userDetailsService(userDetailsService); //配置用户详细服务
  }

发送请求

oauth/token 是Spring Security的内置请求地址。按照如下方式进行请求发送。

  • 21
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要自定义Spring Security OAuth2密码模式登录路径,你可以使用以下步骤: 1. 创建自定义登录页面和控制器,例如/login/custom。 2. 在Spring Security配置类中,使用formLogin()方法启用表单登录,并使用loginPage()方法指定登录页面的路径和permitAll()方法允许所有用户访问登录页面。 ``` @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .anyRequest().authenticated() .and() .formLogin() .loginPage("/login/custom") .permitAll() .and() .oauth2Login() .and() .oauth2Client(); } } ``` 3. 在控制器中,编写处理登录请求的方法,并使用AuthenticationManager.authenticate()方法进行身份验证。如果身份验证成功,重定向到请求的资源,否则返回登录页面。 ``` @Controller public class LoginController { @Autowired private AuthenticationManager authenticationManager; @GetMapping("/login/custom") public String showLoginForm() { return "login"; } @PostMapping("/login/custom") public String submitLoginForm(@RequestParam String username, @RequestParam String password, HttpServletRequest request, HttpServletResponse response) { UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password); try { Authentication authentication = authenticationManager.authenticate(token); SecurityContextHolder.getContext().setAuthentication(authentication); return "redirect:" + request.getParameter("redirect_uri"); } catch (AuthenticationException e) { return "login"; } } } ``` 4. 在OAuth2客户端配置中,使用loginPage()方法指定登录页面的路径。 ``` @Configuration @EnableOAuth2Client public class OAuth2ClientConfig { @Value("${security.oauth2.client.client-id}") private String clientId; @Value("${security.oauth2.client.client-secret}") private String clientSecret; @Value("${security.oauth2.client.access-token-uri}") private String accessTokenUri; @Value("${security.oauth2.client.user-authorization-uri}") private String userAuthorizationUri; @Value("${security.oauth2.client.redirect-uri}") private String redirectUri; @Value("${security.oauth2.client.scope}") private String scope; @Bean public OAuth2ProtectedResourceDetails oauth2ProtectedResourceDetails() { ClientCredentialsResourceDetails details = new ClientCredentialsResourceDetails(); details.setClientId(clientId); details.setClientSecret(clientSecret); details.setAccessTokenUri(accessTokenUri); details.setScope(Arrays.asList(scope.split(","))); return details; } @Bean public OAuth2RestTemplate oauth2RestTemplate() { OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(oauth2ProtectedResourceDetails()); restTemplate.setMessageConverters(Arrays.asList(new MappingJackson2HttpMessageConverter())); return restTemplate; } @Bean public OAuth2ClientContext oauth2ClientContext() { return new DefaultOAuth2ClientContext(new DefaultAccessTokenRequest()); } @Bean public AuthorizationCodeResourceDetails authorizationCodeResourceDetails() { AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails(); details.setClientId(clientId); details.setClientSecret(clientSecret); details.setAccessTokenUri(accessTokenUri); details.setUserAuthorizationUri(userAuthorizationUri); details.setScope(Arrays.asList(scope.split(","))); details.setUseCurrentUri(false); details.setPreEstablishedRedirectUri(redirectUri); details.setAuthenticationScheme(AuthenticationScheme.query); return details; } @Bean public OAuth2RestOperations oauth2RestOperations() { return new OAuth2RestTemplate(authorizationCodeResourceDetails(), oauth2ClientContext()); } @Bean public OAuth2ClientAuthenticationProcessingFilter oauth2ClientAuthenticationProcessingFilter() { OAuth2ClientAuthenticationProcessingFilter filter = new OAuth2ClientAuthenticationProcessingFilter("/login/custom"); OAuth2RestTemplate restTemplate = oauth2RestTemplate(); restTemplate.setAccessTokenProvider(new AuthorizationCodeAccessTokenProvider()); filter.setRestTemplate(restTemplate); UserInfoTokenServices tokenServices = new UserInfoTokenServices(userInfoUri(), clientId); tokenServices.setRestTemplate(restTemplate); filter.setTokenServices(tokenServices); return filter; } @Bean public FilterRegistrationBean oauth2ClientFilterRegistration(OAuth2ClientAuthenticationProcessingFilter filter) { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(filter); registration.setOrder(-100); return registration; } @Value("${security.oauth2.client.user-info-uri}") private String userInfoUri; @Bean public String userInfoUri() { return userInfoUri; } } ``` 这些步骤可以帮助你自定义Spring Security OAuth2密码模式登录路径。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值