Changes between Version 1 and Version 2 of UseCaseImplementationsFinal


Ignore:
Timestamp:
02/04/24 17:49:56 (10 months ago)
Author:
211012
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • UseCaseImplementationsFinal

    v1 v2  
    3030||= ID =||= Use Case =||
    3131|| 18 || Се најавува на системот преку надворешен систем ||
    32 
     32|| 21 || Поврзува профил ||
    3333== Систем
    3434||= ID =||= Use Case =||
     
    3838== Имплементација
    3939=== Се најавува на системот преку надворешен систем
     40[[Image(new_login.png)]]
     41Во последната верзија, со имплементација на OAuth2 клиентот, системот овозможува најава преку користење на профил од Google, Facebook или GitHub. Конфигурацијата е додадена на веќе постоечката за Spring Security, со тоа што дополнително е имплементиран CustomOAuth2AuthenticationService сервис за справување со барањата за регистрација и најава со профил од некој од претходно споментатите провајдери.
     42{{{#!java
     43...
     44                                        .and()
     45                                        .oauth2Login()
     46                                        .loginPage("/login")
     47                                        .permitAll()
     48                                        .userInfoEndpoint(x -> x.userService(customOAuth2UserDetailService))
     49                                        .successHandler(oAuth2SuccessHandler)
     50                                        .failureHandler(oAuth2FailureHandler)
     51...
     52}}}
     53За правилно справување со различните формати на одговор кои секоја од страниците го враќа, преку имплементација на шаблонот за развој на софтвер Factory, имплементиравме фабрика за објекти од типот OAuth2UserDetails, при што во зависност од сценариото соодветно се преземаат потребните атрибути за да може корисникот да идентификува и/или регистрира во нашата база.
     54{{{#!java
     55public abstract class OAuth2UserDetails {
     56    protected Map<String, Object> attributes;
     57
     58    public OAuth2UserDetails(Map<String, Object> attributes) {
     59        this.attributes = attributes;
     60    }
     61
     62    public abstract String getName();
     63    public abstract String getEmail();
     64}
     65}}}
     66{{{#!java
     67public class OAuth2GoogleUser extends OAuth2UserDetails{
     68    public OAuth2GoogleUser(Map<String, Object> attributes) {
     69        super(attributes);
     70    }
     71
     72    @Override
     73    public String getName() {
     74        return (String) attributes.get("name");
     75    }
     76
     77    @Override
     78    public String getEmail() {
     79        return (String) attributes.get("email");
     80    }
     81}
     82}}}
     83{{{#!java
     84public class OAuth2GitHubUser extends OAuth2UserDetails{
     85    public OAuth2GitHubUser(Map<String, Object> attributes) {
     86        super(attributes);
     87    }
     88
     89    @Override
     90    public String getName() {
     91        return (String) attributes.get("name");
     92    }
     93
     94    @Override
     95    public String getEmail() {
     96        return (String) attributes.get("login");
     97    }
     98}
     99}}}
     100{{{#!java
     101public class OAuth2FacebookUser extends OAuth2UserDetails{
     102    public OAuth2FacebookUser(Map<String, Object> attributes) {
     103        super(attributes);
     104    }
     105
     106    @Override
     107    public String getName() {
     108        return (String) attributes.get("name");
     109    }
     110
     111    @Override
     112    public String getEmail() {
     113        return (String) attributes.get("email");
     114    }
     115}
     116}}}
     117{{{#!java
     118public class OAuth2UserDetailsFactory {
     119    public static OAuth2UserDetails createOAuth2UserDetails (String registrationId, Map<String, Object> attributes)
     120    {
     121        if(registrationId.equals(Providers.google.name()))
     122        {
     123            return new OAuth2GoogleUser(attributes);
     124        }
     125        else if(registrationId.equals(Providers.facebook.name()))
     126        {
     127            return new OAuth2FacebookUser(attributes);
     128        }
     129        else if(registrationId.equals(Providers.github.name()))
     130        {
     131            return new OAuth2GitHubUser(attributes);
     132        }
     133        else
     134        {
     135            throw  new RuntimeException("Login with this provider is not supported!");
     136        }
     137    }
     138}
     139}}}
     140Објектот од ваков тип соодветно се креира во сервисот за автентикација преку повик на статичкиот метод.
     141{{{#!java
     142@Service
     143public class CustomOAuth2UserDetailService extends DefaultOAuth2UserService {
     144
     145    private final UsersDao usersDao;
     146
     147    public CustomOAuth2UserDetailService(UsersDao usersDao) {
     148        this.usersDao = usersDao;
     149    }
     150
     151    @Override
     152    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
     153        OAuth2User oAuth2User = super.loadUser(userRequest);
     154
     155        try
     156        {
     157            return checkOAuth2User(userRequest, oAuth2User);
     158        }
     159        catch (AuthenticationException e)
     160        {
     161            throw e;
     162        }
     163        catch (Exception ex)
     164        {
     165            throw ex;
     166        }
     167    }
     168
     169    private OAuth2User checkOAuth2User(OAuth2UserRequest oAuth2UserRequest, OAuth2User oAuth2User)
     170    {
     171        OAuth2UserDetails oAuth2UserDetails = OAuth2UserDetailsFactory
     172                .createOAuth2UserDetails(oAuth2UserRequest.getClientRegistration().getRegistrationId(), oAuth2User.getAttributes());
     173
     174        if(ObjectUtils.isEmpty(oAuth2UserRequest))
     175        {
     176            throw new RuntimeException("Cannot identifty OAuth2 user!");
     177        }
     178
     179        User user = usersDao.findByUsernameAndProvider(
     180                oAuth2UserDetails.getEmail(),
     181                oAuth2UserRequest.getClientRegistration().getRegistrationId());
     182        User userDetails = null;
     183        if(user != null)
     184        {
     185            userDetails = user;
     186            userDetails = updateOAuth2UserDetail(userDetails, oAuth2UserDetails);
     187        }
     188        else
     189        {
     190            userDetails = registerOAuth2UserDetail(oAuth2UserRequest, oAuth2UserDetails);
     191        }
     192        return new OAuth2UserDetailsCustom(
     193                userDetails.getUserID(),
     194                userDetails.getUsername(),
     195                userDetails.getPassword(),
     196                Collections.singletonList(new SimpleGrantedAuthority(userDetails.getRole().getRoleName()))
     197        );
     198    }
     199
     200    public User registerOAuth2UserDetail(OAuth2UserRequest oAuth2UserRequest, OAuth2UserDetails oAuth2UserDetails)
     201    {
     202        Role r = usersDao.findById(1L);
     203        User user = new User();
     204        user.setName(Objects.requireNonNullElse(oAuth2UserDetails.getName(), ""));
     205        user.setEmail(oAuth2UserDetails.getEmail());
     206        user.setProvider(oAuth2UserRequest.getClientRegistration().getRegistrationId());
     207        user.setRole(r);
     208        return usersDao.updateUser(user);
     209    }
     210
     211    public User updateOAuth2UserDetail(User user, OAuth2UserDetails oAuth2UserDetails)
     212    {
     213        user.setEmail(oAuth2UserDetails.getEmail());
     214        return usersDao.mergeUser(user);
     215    }
     216}
     217}}}
     218По креирањето на објект од овој тип, се проверува во базата дали евентуално постои ваков корисник и доколку не, истиот се регистрира. Откако ќе се утврди неговиот статус, функцијата враќа објект од типот OAuth2UserDetailsCustom кој го имплементира UserDetails интерфејсот од Java со што се овозможува да поминува низ филтрите и да се третира исто како и регуларно најавен корисник директно на системот. Доколку најавата е успешна, како и претходно, корисникот се пренасочува кон React апликацијата.
     219{{{#!java
     220    @Override
     221    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
     222        getRedirectStrategy().sendRedirect(request, response, "http://localhost:3000/login-callback");
     223    }
     224}}}
     225=== Поврзува профил