From 82c4c9d0fe09fed20e54fdee02f5ce4d0e05cd92 Mon Sep 17 00:00:00 2001 From: Filip Izydorczyk Date: Mon, 14 Sep 2020 14:02:05 +0200 Subject: [PATCH] Added forbiden urls and protected --- .../repositories/UserRepository.java | 3 + .../com/plannaplan/services/UserService.java | 4 + restservice/pom.xml | 12 +++ .../security/AuthenticationFilter.java | 49 ++++++++++ .../security/AuthenticationProvider.java | 91 +++++++++++++++++++ .../security/WebSecurityConfig.java | 66 ++++++++++++++ 6 files changed, 225 insertions(+) create mode 100644 restservice/src/main/java/com/plannaplan/security/AuthenticationFilter.java create mode 100644 restservice/src/main/java/com/plannaplan/security/AuthenticationProvider.java create mode 100644 restservice/src/main/java/com/plannaplan/security/WebSecurityConfig.java diff --git a/buisnesslogic/src/main/java/com/plannaplan/repositories/UserRepository.java b/buisnesslogic/src/main/java/com/plannaplan/repositories/UserRepository.java index a341ecb..8fbbbb4 100644 --- a/buisnesslogic/src/main/java/com/plannaplan/repositories/UserRepository.java +++ b/buisnesslogic/src/main/java/com/plannaplan/repositories/UserRepository.java @@ -11,4 +11,7 @@ import org.springframework.stereotype.Repository; public interface UserRepository extends JpaRepository { @Query("FROM User WHERE email = ?1") User getByAuthority(@Param("authority") String authority); + + @Query("FROM User WHERE token = ?1") + User getByToken(@Param("token") String token); } \ No newline at end of file diff --git a/buisnesslogic/src/main/java/com/plannaplan/services/UserService.java b/buisnesslogic/src/main/java/com/plannaplan/services/UserService.java index 3bdcfa7..0fec12f 100644 --- a/buisnesslogic/src/main/java/com/plannaplan/services/UserService.java +++ b/buisnesslogic/src/main/java/com/plannaplan/services/UserService.java @@ -38,4 +38,8 @@ public class UserService extends EventWatcher { return this.repo.getByAuthority(email.replace("\n", "").trim()); } + public User getByToken(String token) { + return this.repo.getByToken(token); + } + } \ No newline at end of file diff --git a/restservice/pom.xml b/restservice/pom.xml index bd3a2dc..d941ad1 100644 --- a/restservice/pom.xml +++ b/restservice/pom.xml @@ -42,6 +42,12 @@ spring-boot-starter-web + + org.springframework.boot + spring-boot-starter-security + 2.3.3.RELEASE + + org.springframework.boot spring-boot-starter-test @@ -54,6 +60,12 @@ + + org.apache.commons + commons-lang3 + 3.8.1 + + buisnesslogic com.plannaplan diff --git a/restservice/src/main/java/com/plannaplan/security/AuthenticationFilter.java b/restservice/src/main/java/com/plannaplan/security/AuthenticationFilter.java new file mode 100644 index 0000000..3ebfe13 --- /dev/null +++ b/restservice/src/main/java/com/plannaplan/security/AuthenticationFilter.java @@ -0,0 +1,49 @@ +package com.plannaplan.security; + +import java.io.IOException; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; +import org.springframework.security.web.util.matcher.RequestMatcher; + +import static org.springframework.http.HttpHeaders.AUTHORIZATION; + +public class AuthenticationFilter extends AbstractAuthenticationProcessingFilter { + + AuthenticationFilter(final RequestMatcher requiresAuth) { + super(requiresAuth); + } + + @Override + public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) + throws AuthenticationException, IOException, ServletException { + + String token = request.getHeader(AUTHORIZATION); + if (token == null) { + token = ""; + } else { + token = StringUtils.removeStart(token, "Bearer").trim(); + } + Authentication requestAuthentication = new UsernamePasswordAuthenticationToken(token, token); + return getAuthenticationManager().authenticate(requestAuthentication); + + } + + @Override + protected void successfulAuthentication(final HttpServletRequest request, final HttpServletResponse response, + final FilterChain chain, final Authentication authResult) throws IOException, ServletException { + SecurityContextHolder.getContext().setAuthentication(authResult); + + chain.doFilter(request, response); + } + +} \ No newline at end of file diff --git a/restservice/src/main/java/com/plannaplan/security/AuthenticationProvider.java b/restservice/src/main/java/com/plannaplan/security/AuthenticationProvider.java new file mode 100644 index 0000000..aa9ff3d --- /dev/null +++ b/restservice/src/main/java/com/plannaplan/security/AuthenticationProvider.java @@ -0,0 +1,91 @@ +package com.plannaplan.security; + +import java.util.Collection; + +import com.plannaplan.entities.User; +import com.plannaplan.services.UserService; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Component; + +@Component +public class AuthenticationProvider extends AbstractUserDetailsAuthenticationProvider { + + @Autowired + private UserService userService; + + @Override + protected void additionalAuthenticationChecks(UserDetails userDetails, + UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { + // TODO Auto-generated method stub + + } + + @Override + protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) + throws AuthenticationException { + + String token = authentication.getCredentials().toString(); + + User user = this.userService.getByToken(token); + + if (user == null) { + throw new UsernameNotFoundException("Cannot find user with authentication token=" + token); + } + + UserDetails response = new UserDetails() { + + /** + * + */ + private static final long serialVersionUID = 1L; + + @Override + public Collection getAuthorities() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getPassword() { + return null; + } + + @Override + public String getUsername() { + return user.getName() + " " + user.getSurname(); + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return true; + } + + @Override + public boolean isCredentialsNonExpired() { + // TODO Auto-generated method stub + return true; + } + + @Override + public boolean isEnabled() { + return true; + } + + }; + + return response; + } + +} diff --git a/restservice/src/main/java/com/plannaplan/security/WebSecurityConfig.java b/restservice/src/main/java/com/plannaplan/security/WebSecurityConfig.java new file mode 100644 index 0000000..29850bc --- /dev/null +++ b/restservice/src/main/java/com/plannaplan/security/WebSecurityConfig.java @@ -0,0 +1,66 @@ +package com.plannaplan.security; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; +import org.springframework.security.web.util.matcher.OrRequestMatcher; +import org.springframework.security.web.util.matcher.RequestMatcher; +import org.springframework.http.HttpStatus; +import org.springframework.security.web.authentication.AnonymousAuthenticationFilter; +import org.springframework.security.web.authentication.HttpStatusEntryPoint; + +@Configuration +@EnableWebSecurity +public class WebSecurityConfig extends WebSecurityConfigurerAdapter { + + private static final RequestMatcher PROTECTED_URLS = new OrRequestMatcher(new AntPathRequestMatcher("/api/**")); + + AuthenticationProvider provider; + + public WebSecurityConfig(final AuthenticationProvider authenticationProvider) { + super(); + this.provider = authenticationProvider; + } + + @Override + protected void configure(final AuthenticationManagerBuilder auth) { + auth.authenticationProvider(provider); + } + + @Override + public void configure(final WebSecurity webSecurity) { + webSecurity.ignoring().antMatchers("/token**"); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.csrf().disable().formLogin().disable().httpBasic().disable().logout().disable().sessionManagement() + .sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().exceptionHandling().and() + .authenticationProvider(provider) + .addFilterBefore(authenticationFilter(), AnonymousAuthenticationFilter.class).authorizeRequests() + .antMatchers(HttpMethod.GET, "/token**").permitAll().anyRequest().authenticated(); + + } + + @Bean + AuthenticationFilter authenticationFilter() throws Exception { + final AuthenticationFilter filter = new AuthenticationFilter(PROTECTED_URLS); + filter.setAuthenticationManager(authenticationManager()); + // filter.setAuthenticationSuccessHandler(successHandler()); + return filter; + } + + @Bean + AuthenticationEntryPoint forbiddenEntryPoint() { + return new HttpStatusEntryPoint(HttpStatus.FORBIDDEN); + } + +}