RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 1065691
Accepted
Orkhan Hasanli
Orkhan Hasanli
Asked:2020-01-04 04:43:48 +0000 UTC2020-01-04 04:43:48 +0000 UTC 2020-01-04 04:43:48 +0000 UTC

如何在 Spring Boot 中正确结合 OAuth 授权和常规授权?

  • 772

我正在使用以下配置通过 oauth 和常规授权来实现授权。

@Override
protected void configure(HttpSecurity http) throws Exception {
            http
                    .authorizeRequests().mvcMatchers("/robots.txt").permitAll()
                    .antMatchers(
                            "/", "/auth", "/signup", "/restore", "/activation/**",
                            "/admin/login", "/admin_restore",
                            "/agreement", "/privacy", "/about-us", "/faq", "/contact-us",
                            "/error",
                            "/page/**", "/categories", "/categories/**"
                    ).permitAll()
                    .anyRequest().authenticated()

                    .and()
                        .formLogin()
                        .loginPage("/auth")
                        .loginProcessingUrl("/auth")
                        .usernameParameter("email")
                        .passwordParameter("password")
                        .defaultSuccessUrl("/")
                        .failureUrl("/auth?authError")
                        .permitAll()

                    .and()
                        .rememberMe()
                        .rememberMeParameter("remember-me")
                        .tokenValiditySeconds(86400)

                    .and()
                        .logout()
                        .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                        .logoutSuccessUrl("/")
                        .deleteCookies("JSESSIONID")

                    .and()
                        .oauth2Login().defaultSuccessUrl("/oauth")

                    .and()
                        .exceptionHandling()
                        .accessDeniedPage("/403")

                    .and()
                        .csrf()

                    .and()
                        .sessionManagement()
                        .sessionCreationPolicy(SessionCreationPolicy.ALWAYS)

                    .and()
                        .headers().frameOptions().sameOrigin();
        }

原则上,授权可以正常工作。但!我还需要在授权用户时确定他的授权日期和时间。我已经实现了常规授权的工作功能,但是 OAuth2 授权存在问题。

@Service
public class UserService implements
        ApplicationListener<AuthenticationSuccessEvent> {

/** 
Переопределяем метод onApplicationEvent(), чтобы при авторизации юзера зафиксировать дату и время его авторизации
   */
  @Override
  public void onApplicationEvent(AuthenticationSuccessEvent event) {
    >>> Ex.here!  String userEmail = ((UserDetails) event.getAuthentication().
            getPrincipal()).getUsername();
    User user = this.userRepository.findByUserEmail(userEmail);
    user.setLastAuthDate(LocalDateTime.now());
    userRepository.save(user);
  }
...
}

如果通过oauth登录,则会出现以下异常:

java.lang.ClassCastException: org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser cannot be cast to org.springframework.security.core.userdetails.UserDetails

因此,问题是 - 如何消除此异常,以便 oauth 用户在进入站点时的授权也是固定的?如何区分普通用户和 oauth 授权用户?我有一个问题......

预先感谢您的帮助!

spring
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    Orkhan Hasanli
    2020-01-04T09:04:56Z2020-01-04T09:04:56Z

    一般来说,多亏了关于检查授权类型的提示,我解决了这个问题。我不知道执行任务的结果如何,但代码正在运行。

     @Override
      public void onApplicationEvent(ApplicationEvent appEvent) {
    
        if (appEvent instanceof AuthenticationSuccessEvent)
        {
          AuthenticationSuccessEvent event = (AuthenticationSuccessEvent) appEvent;
    
          if (event.getAuthentication() instanceof UsernamePasswordAuthenticationToken) {
            String userEmail = ((UserDetails) event.getAuthentication().
                    getPrincipal()).getUsername();
            User user = this.userRepository.findByUserEmail(userEmail);
            user.setLastAuthDate(LocalDateTime.now());
            userRepository.save(user);
    
          } else if (event.getAuthentication() instanceof OAuth2LoginAuthenticationToken) {
    
            Authentication authentication = event.getAuthentication();
    
            OAuth2LoginAuthenticationToken oAuth2LoginAuthenticationToken = (OAuth2LoginAuthenticationToken) authentication;
    
            OAuth2AuthorizedClient client = authorizedClientService
                    .loadAuthorizedClient(
                            oAuth2LoginAuthenticationToken.getClientRegistration().getRegistrationId(),
                            oAuth2LoginAuthenticationToken.getName());
    
            String userInfoEndpointUri = oAuth2LoginAuthenticationToken.getClientRegistration()
                    .getProviderDetails().getUserInfoEndpoint().getUri();
    
            String userFullname = "";
            String userEmail = "";
    
            if (!StringUtils.isEmpty(userInfoEndpointUri)) {
              RestTemplate restTemplate = new RestTemplate();
              HttpHeaders headers = new HttpHeaders();
              headers.add(HttpHeaders.AUTHORIZATION, "Bearer " + oAuth2LoginAuthenticationToken.getAccessToken()
                      .getTokenValue());
              HttpEntity entity = new HttpEntity("", headers);
              ResponseEntity<Map> response = restTemplate
                      .exchange(userInfoEndpointUri, HttpMethod.GET, entity, Map.class);
              Map userAttributes = response.getBody();
    
              userFullname = userAttributes.get("name").toString();
              userEmail = userAttributes.get("email").toString();
    
            }
    
            User userFromDbEmail = this.userRepository.findByUserEmail(userEmail);
    
            // Добавить нового пользователя авторизованого через oAuth
            if(userFromDbEmail == null) {
    
              User user = new User();
              user.setUserEmail(userEmail);
              user.setUserFullname(userFullname);
              user.setUserActive(true);
              user.setRegDate(LocalDateTime.now());
              user.setLastAuthDate(LocalDateTime.now());
              user.setUserRating(0);
              user.setReceiveMessageEmails(true);
              user.setReceiveNotificationEmails(true);
              user.getRoles().add(Role.USER);
              userRepository.save(user);
    
            } else {
    
              userFromDbEmail.setLastAuthDate(LocalDateTime.now());
              userRepository.save(userFromDbEmail);
            }
    
          }
    
        }
    
      }
    

    我们捕获 AuthenticationSuccessEvent 并查看它的类型。基本授权 - UsernamePasswordAuthenticationToken OAuth2 授权 - OAuth2LoginAuthenticationToken

    进一步,如果正常授权,那么我们在数据库中查找用户并修复当前授权时间。如果 oauth2 授权,如果这个用户不在数据库中,那么我们创建它,如果这个用户存在,那么我们找到它并修复最后一次授权的时间。

    • 0

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    如何从列表中打印最大元素(str 类型)的长度?

    • 2 个回答
  • Marko Smith

    如何在 PyQT5 中清除 QFrame 的内容

    • 1 个回答
  • Marko Smith

    如何将具有特定字符的字符串拆分为两个不同的列表?

    • 2 个回答
  • Marko Smith

    导航栏活动元素

    • 1 个回答
  • Marko Smith

    是否可以将文本放入数组中?[关闭]

    • 1 个回答
  • Marko Smith

    如何一次用多个分隔符拆分字符串?

    • 1 个回答
  • Marko Smith

    如何通过 ClassPath 创建 InputStream?

    • 2 个回答
  • Marko Smith

    在一个查询中连接多个表

    • 1 个回答
  • Marko Smith

    对列表列表中的所有值求和

    • 3 个回答
  • Marko Smith

    如何对齐 string.Format 中的列?

    • 1 个回答
  • Martin Hope
    Alexandr_TT 2020年新年大赛! 2020-12-20 18:20:21 +0000 UTC
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5