Changes between Version 10 and Version 11 of UseCaseImplementations


Ignore:
Timestamp:
02/04/24 13:52:06 (5 months ago)
Author:
211012
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • UseCaseImplementations

    v10 v11  
    156156== Се најавува на системот
    157157[[Image(login.png)]]
    158 
     158Најавата на системот е имплементирана директно на серверската апликација односно на адресата http://localhost:8080/login, каде што се прикажува страницата од сликата. За реализација на ова сценарио користиме Spring Security каде синџирот филтри е соодветно конфигуриран да одговори на нашите потреби, односно да ги филтрира барањата во зависност од тоа дали корисницте се автентицирани, имаат одредена привилегија или пристапуваат до нивен ресурс.
     159{{{#!java
     160        @Bean
     161    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
     162        http
     163                .csrf().disable()
     164                .authorizeHttpRequests((authz) -> {
     165                            try {
     166                                authz
     167                                        .requestMatchers(new AntPathRequestMatcher("/{userId}/hasBusiness")).access(userSecurity)
     168                                        .requestMatchers(new AntPathRequestMatcher("/business/*/unapproved")).authenticated()
     169                                        .requestMatchers(new AntPathRequestMatcher("/register")).permitAll()
     170                                        .requestMatchers(new AntPathRequestMatcher("/hotel/search")).permitAll()
     171                                        .requestMatchers(new AntPathRequestMatcher("/transport/search")).permitAll()
     172                                        .requestMatchers(new AntPathRequestMatcher("/restaurant/search")).permitAll()
     173                                        .requestMatchers(new AntPathRequestMatcher("/upload")).permitAll()
     174                                        .requestMatchers(new AntPathRequestMatcher("/business/approve/*")).hasAnyAuthority("SUPERADMIN")
     175                                        .requestMatchers(new AntPathRequestMatcher("/users/unlock/*")).hasAnyAuthority("SUPERADMIN")
     176                                        .requestMatchers(new AntPathRequestMatcher("/users/approve/*")).hasAnyAuthority("SUPERADMIN")
     177                                        .requestMatchers(new AntPathRequestMatcher("/business/unapproved")).hasAnyAuthority("SUPERADMIN")
     178                                        .requestMatchers(new AntPathRequestMatcher("/business/add/*")).authenticated()
     179                                        .requestMatchers(new AntPathRequestMatcher("/*/user/{userId}")).access(userSecurity)
     180                                        .anyRequest().authenticated()
     181                                        .and()
     182                                        .formLogin()
     183                                        .loginPage("/login")
     184                                        .successHandler(oAuth2SuccessHandler)
     185                                        .permitAll()
     186                                        .permitAll()
     187                                        .and()
     188                                        .sessionManagement()
     189                                        .sessionCreationPolicy(SessionCreationPolicy.ALWAYS)
     190                                        .and()
     191                                        .logout().logoutSuccessHandler((new HttpStatusReturningLogoutSuccessHandler(HttpStatus.OK)))
     192                                        .permitAll();
     193
     194                            } catch (Exception e) {
     195                                throw new RuntimeException(e);
     196                            }
     197                        }
     198                ).httpBasic();
     199        return http.build();
     200    }
     201}
     202
     203}}}
     204За да се провери идентитетот на корисникот, односно дали тој е сопственик на ресурсите кои се обидува да ги пристапи е имплементирана следната компонента.
     205{{{#!java
     206@Component
     207public class UserSecurity implements AuthorizationManager<RequestAuthorizationContext> {
     208
     209    @Override
     210    public AuthorizationDecision check(Supplier authenticationSupplier, RequestAuthorizationContext ctx) {
     211        Long userId = Long.parseLong(ctx.getVariables().get("userId"));
     212        Authentication authentication = (Authentication) authenticationSupplier.get();
     213        return new AuthorizationDecision(hasUserId(authentication, userId));
     214    }
     215
     216    public boolean hasUserId(Authentication authentication, Long userId) {
     217        Long id;
     218        User user = (User) authentication.getPrincipal();
     219        id = user.getUserID();
     220        return userId == id;
     221    }
     222
     223}
     224}}}
     225По успешната најава, серверот го пренасочува корисникот до клиентската апликација односно http://localhost:8080/login-callback по што, преку Hook-от useLogin се испраќа барање за добивање на податоците и нивно зачувување во AuthContext-от, од каде можат сите компоненти да ги пристапат.
     226{{{#!javascript
     227
     228const useLogin = () => {
     229        const [loading, setLoading] = useState(false);
     230        const [error, setError] = useState(null);
     231        const Auth = useAuth();
     232
     233        const handleLoginCallback = async () => {
     234                setLoading(true);
     235
     236                try {
     237                        const response = await axios.get("http://localhost:8080/principal");
     238                        const { id, role, username } = response.data;
     239                       
     240                        Auth.userLogin({userId: id, username: username, role: role})
     241
     242                } catch (err) {
     243                        setError(err.message);
     244                } finally {
     245                        setLoading(false);
     246                }
     247        };
     248
     249        return {
     250                loading,
     251                error,
     252                handleLoginCallback,
     253        };
     254};
     255
     256export default useLogin;
     257}}}
     258\\
     259{{{#!javascript
     260const AuthContext = createContext()
     261
     262const AuthProvider = ({ children }) => {
     263    const [user, setUser] = useState(null)
     264
     265    useEffect(() => {
     266        const storedUser = JSON.parse(localStorage.getItem('user'))
     267        setUser(storedUser)
     268    }, [])
     269
     270    const getUser = () => {
     271        return JSON.parse(localStorage.getItem('user'))
     272    }
     273
     274    const userIsAuthenticated = () => {
     275        return localStorage.getItem('user') !== null
     276    }
     277
     278    const userLogin = user => {
     279        localStorage.setItem('user', JSON.stringify(user))
     280        setUser(user)
     281    }
     282
     283    const userLogout = () => {
     284        localStorage.removeItem('user')
     285        setUser(null)
     286    }
     287
     288    const contextValue = {
     289        user,
     290        getUser,
     291        userIsAuthenticated,
     292        userLogin,
     293        userLogout,
     294    }
     295
     296    return (
     297        <AuthContext.Provider value={contextValue}>
     298            {children}
     299        </AuthContext.Provider>
     300    )
     301}
     302
     303export default AuthContext
     304
     305export function useAuth() {
     306    return useContext(AuthContext)
     307}
     308
     309export { AuthProvider }
     310}}}
     311За да се заштитат рутите за кои е потребна автентикација, имплементирана е wrapper-компонента којашто проверува дали корисникот е најавен и во спротивно го пренасочува кон страницата за најава.
     312{{{#!javascript
     313function PrivateRoute({ children }) {
     314  const { userIsAuthenticated } = useAuth()
     315  if(userIsAuthenticated())
     316  {
     317    return children;
     318  }
     319  else
     320  {
     321    window.location.href = "http://localhost:8080/login";
     322  }
     323}
     324
     325export default PrivateRoute
     326}}}
    159327== Се регистрира на системот
    160328[[Image(registartion.png)]]
    161 
     329Регистрацијата не е никаков специјален случај, туку обично POST барање кое се испраќа по пополнување на формуларот. Него го пречекува следниот контролер и го препраќа на обработка до сервисот и Dao-то
     330{{{#!java
     331    @PostMapping(path = "/register")
     332    public List<User> add(@RequestBody User user) {
     333        usersManager.createUser(user.getName(), user.getSurname(), user.getEmail(), user.getBirthDate(), user.getAddress(), user.getContact());
     334        return usersManager.getCreatedUsers();
     335    }
     336}}}
    162337== Корисник со основни привилегии
    163338=== Листа сместувања