Merge pull request 'security' (#9) from security into master

Reviewed-on: http://git.plannaplan.pl/filipizydorczyk/backend/pulls/9
This commit is contained in:
Marcin Woźniak 2020-09-15 17:27:04 +02:00
commit 579da3f038
19 changed files with 577 additions and 28 deletions

View File

@ -1,5 +1,7 @@
package com.plannaplan.entities; package com.plannaplan.entities;
import java.sql.Date;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.GeneratedValue; import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType; import javax.persistence.GenerationType;
@ -14,11 +16,35 @@ public class User {
private Long id; private Long id;
private String name; private String name;
private String surname; private String surname;
private String email;
private UserRoles role; private UserRoles role;
private String token;
private Date tokenCreatedDate;
public User() { public User() {
} }
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Date getTokenCreatedDate() {
return tokenCreatedDate;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.tokenCreatedDate = new Date(System.currentTimeMillis());
this.token = token;
}
public String getName() { public String getName() {
return name; return name;
} }

View File

@ -0,0 +1,13 @@
package com.plannaplan.exceptions;
public class UserNotFoundException extends Exception {
/**
*
*/
private static final long serialVersionUID = 1L;
public UserNotFoundException(String message) {
super(message);
}
}

View File

@ -3,9 +3,15 @@ package com.plannaplan.repositories;
import com.plannaplan.entities.User; import com.plannaplan.entities.User;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
@Repository @Repository
public interface UserRepository extends JpaRepository<User, Long> { public interface UserRepository extends JpaRepository<User, Long> {
@Query("FROM User WHERE email = ?1")
User getByAuthority(@Param("authority") String authority);
@Query("FROM User WHERE token = ?1")
User getByToken(@Param("token") String token);
} }

View File

@ -1,6 +1,10 @@
package com.plannaplan.services; package com.plannaplan.services;
import java.util.UUID;
import com.plannaplan.abstracts.EventWatcher; import com.plannaplan.abstracts.EventWatcher;
import com.plannaplan.entities.User;
import com.plannaplan.exceptions.UserNotFoundException;
import com.plannaplan.repositories.UserRepository; import com.plannaplan.repositories.UserRepository;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -15,4 +19,27 @@ public class UserService extends EventWatcher {
super(); super();
} }
public String login(String authority) throws UserNotFoundException {
User user = this.repo.getByAuthority(authority.replace("\n", "").trim());
if (user == null) {
throw new UserNotFoundException("Can not find user with given authority");
}
String token = UUID.randomUUID().toString();
user.setToken(token);
this.repo.save(user);
return token;
}
public void save(User user) {
this.repo.save(user);
}
public User getUserByEmail(String email) {
return this.repo.getByAuthority(email.replace("\n", "").trim());
}
public User getByToken(String token) {
return this.repo.getByToken(token);
}
} }

View File

@ -1,5 +1,5 @@
package com.plannaplan.types; package com.plannaplan.types;
public enum UserRoles { public enum UserRoles {
STUDENT, DEANERY, ADMIN STUDENT, DEANERY, ADMIN, TEST_USER
} }

View File

@ -0,0 +1,64 @@
package com.plannaplan.services;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import static org.junit.jupiter.api.Assertions.assertTrue;
import com.plannaplan.entities.User;
import com.plannaplan.exceptions.UserNotFoundException;
import com.plannaplan.types.UserRoles;
import org.junit.Before;
import org.junit.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
import org.junit.runner.RunWith;
@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration
@TestMethodOrder(OrderAnnotation.class)
public class UserServiceTest {
public static String TEST_USER_MAIL = "noteexisitingmail@notexistingdomain.com";
public static String TEST_USER_NAME = "Tom";
public static String TEST_USER_SUERNAME = "Kovalsky";
@Autowired
UserService userService;
@Before
public void initialize() {
User testUser = new User();
testUser.setEmail(TEST_USER_MAIL);
testUser.setName(TEST_USER_NAME);
testUser.setSurname(TEST_USER_SUERNAME);
testUser.setRole(UserRoles.TEST_USER);
this.userService.save(testUser);
}
@Test
public void shouldReturnToken() {
try {
String token = this.userService.login(TEST_USER_MAIL);
System.out.println("Returned token: " + token);
assertTrue(token != null);
assertTrue(this.userService.getUserByEmail(TEST_USER_MAIL).getToken() != null);
} catch (UserNotFoundException e) {
e.printStackTrace();
assertTrue(false);
}
}
@Test
public void shouldThrowException() {
try {
this.userService.login("thiseamilisnotindatabase@gmail.com");
assertTrue(false);
} catch (UserNotFoundException e) {
assertTrue(true);
}
}
}

View File

@ -1,11 +1,12 @@
# Dokumetacja API # Dokumetacja API
| Api | Zadania endpointa | | Api | Zadania endpointa |
| ---------------------------------------------- | ---------------------------------------------------------- | | ------------------------------------------------------------- | ---------------------------------------------------------------------------- |
| [/config](#config) | Załadowanie konfiguracji startowej do aplikacji PlanNaPlan | | [/api/v1/configurator/config](#config) | Załadowanie konfiguracji startowej do aplikacji PlanNaPlan |
| [/getCoursesWithGroups](#getcourseswithgroups) | Zwrócenie wszytskich kursów razem z grupami | | [/api/v1/courses/getCoursesWithGroups](#getcourseswithgroups) | Zwrócenie wszytskich kursów razem z grupami |
| [/getCourseGroups](#getcoursegroups) | Zwrócenie grup dla danego kursu | | [/api/v1/groups/getCourseGroups](#getcoursegroups) | Zwrócenie grup dla danego kursu |
| [/getCourses](#getcourses) | Zwrócenie wszystkich kursów | | [/api/v1/courses/getCourses](#getcourses) | Zwrócenie wszystkich kursów |
| [/token](#token) | Wymienia ticket z CAS-a na token ktorym beda autoryzowane chronione requesty |
## config ## config
@ -30,7 +31,7 @@ Endpoint konfigurujacy caly system i importujacy dane do bazy.
Source code: [link](../restservice/src/main/java/com/plannaplan/controllers/getCoursesWithGroups.java) Source code: [link](../restservice/src/main/java/com/plannaplan/controllers/getCoursesWithGroups.java)
``` ```
GET /getCoursesWithGroups GET /api/v1/courses/getCoursesWithGroups
``` ```
#### Opis #### Opis
@ -42,7 +43,7 @@ Zwraca wszystkie dostepne kursy wraz z listą grup.
Source code: [link](../restservice/src/main/java/com/plannaplan/controllers/GroupController.java) Source code: [link](../restservice/src/main/java/com/plannaplan/controllers/GroupController.java)
``` ```
GET /getCourseGroups GET /api/v1/groups/getCourseGroups
``` ```
#### Opis #### Opis
@ -61,9 +62,27 @@ Zwraca wszytskie grupy dla danego kursu.
Source code: [link](../restservice/src/main/java/com/plannaplan/controllers/CoursesController.java) Source code: [link](../restservice/src/main/java/com/plannaplan/controllers/CoursesController.java)
``` ```
GET /getCourses GET /api/v1/courses/getCourses
``` ```
#### Opis #### Opis
Zwraca wszystkie dostepne kursy. Zwraca wszystkie dostepne kursy.
## token
Source code: [link](../restservice/src/main/java/com/plannaplan/controllers/TokenController.java)
```
GET /token?ticket=ST-668405-W0gfvSVDRBdMUWLweKzv-cas.amu.edu.pl
```
#### Opis
Po odpytaniu tego endpointa z podanym ticketem system zrobi nma nim validate i dostanie uzytkownika dla ktorego zostal on wygenerowany. System utworzy dla niego access token i go zwroci w odpowiedzi
#### Parametry
| Type | Name | Consumes | Opis | Type |
| ----------- | ------------------------- | -------- | --------------------------------------- | ------ |
| Query Param | **ticket** </br> required | - | ticket uzyskany z logowania poprzez CAS | string |

View File

@ -31,11 +31,23 @@
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.10</version>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-web</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>2.3.3.RELEASE</version>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>
@ -48,6 +60,12 @@
</exclusions> </exclusions>
</dependency> </dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8.1</version>
</dependency>
<dependency> <dependency>
<artifactId>buisnesslogic</artifactId> <artifactId>buisnesslogic</artifactId>
<groupId>com.plannaplan</groupId> <groupId>com.plannaplan</groupId>

View File

@ -1,15 +1,38 @@
package com.plannaplan; package com.plannaplan;
import com.plannaplan.entities.User;
import com.plannaplan.services.UserService;
import com.plannaplan.types.UserRoles;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
@SpringBootApplication @SpringBootApplication
public class App { public class App {
public final static String API_VERSION = "v1";
@Autowired
UserService userService;
public static void main(String[] args) { public static void main(String[] args) {
Logo logo = new Logo("beta"); Logo logo = new Logo("beta");
System.out.println(logo.getLogo()); System.out.println(logo.getLogo());
System.out.println("|=============================================================================================|"); System.out.println(
"|=============================================================================================|");
SpringApplication.run(App.class, args); SpringApplication.run(App.class, args);
} }
@EventListener(ApplicationReadyEvent.class)
public void importData() {
User testUser = new User();
testUser.setEmail("filizy@st.amu.edu.pl");
testUser.setName("Filip");
testUser.setSurname("Izydorczyk");
testUser.setRole(UserRoles.STUDENT);
this.userService.save(testUser);
}
} }

View File

@ -5,6 +5,7 @@ import org.springframework.web.bind.annotation.RestController;
import java.io.IOException; import java.io.IOException;
import com.plannaplan.App;
import com.plannaplan.Controller; import com.plannaplan.Controller;
import com.plannaplan.models.ConfigData; import com.plannaplan.models.ConfigData;
@ -12,11 +13,13 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
@RestController @RestController
@CrossOrigin @CrossOrigin
@RequestMapping("/api/" + App.API_VERSION + "/configurator")
public class ConfigController { public class ConfigController {
@Autowired @Autowired

View File

@ -5,6 +5,7 @@ import java.util.Dictionary;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.List; import java.util.List;
import com.plannaplan.App;
import com.plannaplan.entities.Course; import com.plannaplan.entities.Course;
import com.plannaplan.entities.Groups; import com.plannaplan.entities.Groups;
import com.plannaplan.services.CourseService; import com.plannaplan.services.CourseService;
@ -15,21 +16,23 @@ import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@RestController @RestController
@CrossOrigin @CrossOrigin
@RequestMapping("/api/" + App.API_VERSION + "/courses")
public class CoursesController { public class CoursesController {
@Autowired @Autowired
private CourseService courseService; private CourseService courseService;
@GetMapping("/getCourses") @GetMapping("/getCourses")
public ResponseEntity<List<Dictionary<String,Object>>> getMethodName() { public ResponseEntity<List<Dictionary<String, Object>>> getMethodName() {
List<Course> courses = this.courseService.getAllCourses(); List<Course> courses = this.courseService.getAllCourses();
List<Dictionary<String,Object>> response = new ArrayList<>(); List<Dictionary<String, Object>> response = new ArrayList<>();
for(Course c : courses){ for (Course c : courses) {
Dictionary<String, Object> element = new Hashtable<>(); Dictionary<String, Object> element = new Hashtable<>();
element.put("id", c.getId()); element.put("id", c.getId());
element.put("name",c.getName()); element.put("name", c.getName());
response.add(element); response.add(element);
} }
@ -37,16 +40,16 @@ public class CoursesController {
} }
@GetMapping("/getCoursesWithGroups") @GetMapping("/getCoursesWithGroups")
public ResponseEntity<List<Dictionary<String,Object>>> getCoursesWithGroups() { public ResponseEntity<List<Dictionary<String, Object>>> getCoursesWithGroups() {
List<Course> courses = this.courseService.getAllCourses(); List<Course> courses = this.courseService.getAllCourses();
List<Dictionary<String,Object>> response = new ArrayList<>(); List<Dictionary<String, Object>> response = new ArrayList<>();
for(Course c : courses){ for (Course c : courses) {
Dictionary<String, Object> element = new Hashtable<>(); Dictionary<String, Object> element = new Hashtable<>();
element.put("id", c.getId()); element.put("id", c.getId());
element.put("name",c.getName()); element.put("name", c.getName());
List<Dictionary<String,Object>> groups = new ArrayList<>(); List<Dictionary<String, Object>> groups = new ArrayList<>();
for(Groups g : c.getGroups()){ for (Groups g : c.getGroups()) {
Dictionary<String,Object> group = new Hashtable<>(); Dictionary<String, Object> group = new Hashtable<>();
group.put("id", g.getId()); group.put("id", g.getId());
group.put("day", g.getDay().label); group.put("day", g.getDay().label);
group.put("time", g.getTimeString()); group.put("time", g.getTimeString());

View File

@ -5,6 +5,7 @@ import java.util.Dictionary;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.List; import java.util.List;
import com.plannaplan.App;
import com.plannaplan.entities.Groups; import com.plannaplan.entities.Groups;
import com.plannaplan.services.GroupService; import com.plannaplan.services.GroupService;
@ -13,21 +14,23 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
@RestController @RestController
@CrossOrigin @CrossOrigin
@RequestMapping("/api/" + App.API_VERSION + "/groups")
public class GroupController { public class GroupController {
@Autowired @Autowired
private GroupService groupService; private GroupService groupService;
@GetMapping("/getCourseGroups") @GetMapping("/getCourseGroups")
public ResponseEntity<List<Dictionary<String, Object>>> getCourses(@RequestParam("id") Long id, @RequestParam(name="capacity", defaultValue="true") Boolean capacity){ public ResponseEntity<List<Dictionary<String, Object>>> getCourses(@RequestParam("id") Long id,
@RequestParam(name = "capacity", defaultValue = "true") Boolean capacity) {
List<Groups> groups = this.groupService.getGroupsByCourse(id); List<Groups> groups = this.groupService.getGroupsByCourse(id);
List<Dictionary<String, Object>> response = new ArrayList<>(); List<Dictionary<String, Object>> response = new ArrayList<>();
for (Groups g : groups) { for (Groups g : groups) {
Dictionary<String, Object> group = new Hashtable<>(); Dictionary<String, Object> group = new Hashtable<>();
group.put("id", g.getId()); group.put("id", g.getId());

View File

@ -0,0 +1,42 @@
package com.plannaplan.controllers;
import com.plannaplan.exceptions.UserNotFoundException;
import com.plannaplan.security.CasValidationExcepiton;
import com.plannaplan.security.CasValidator;
import com.plannaplan.services.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@CrossOrigin
public class TokenController {
public static String SERVICE_URL = "http://localhost:3000";
@Autowired
private UserService userService;
@GetMapping("/token")
public ResponseEntity<String> getToken(@RequestParam("ticket") final String ticket) {
CasValidator validator = new CasValidator(SERVICE_URL, ticket);
try {
String authority = validator.validate();
String token = this.userService.login(authority);
return new ResponseEntity<>(token, HttpStatus.OK);
} catch (CasValidationExcepiton e) {
return new ResponseEntity<>("Wrong ticket", HttpStatus.UNAUTHORIZED);
} catch (UserNotFoundException e) {
return new ResponseEntity<>("User not found", HttpStatus.NOT_FOUND);
} catch (Exception e) {
return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}

View File

@ -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);
}
}

View File

@ -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<? extends GrantedAuthority> 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;
}
}

View File

@ -0,0 +1,13 @@
package com.plannaplan.security;
public class CasValidationExcepiton extends RuntimeException {
/**
*
*/
private static final long serialVersionUID = 1L;
public CasValidationExcepiton(String s) {
super(s);
}
}

View File

@ -0,0 +1,45 @@
package com.plannaplan.security;
import java.net.URLEncoder;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
public class CasValidator {
private static String CAS_URL = "https://cas.amu.edu.pl/cas";
private final CloseableHttpClient httpClient = HttpClients.createDefault();
private String service;
private String ticket;
public CasValidator(String service, String ticket) {
this.service = service;
this.ticket = ticket;
}
public String validate() throws Exception, CasValidationExcepiton{
HttpGet request = new HttpGet(CasValidator.CAS_URL + "/validate?service="
+ URLEncoder.encode(this.service, "UTF-8") + "&ticket=" + URLEncoder.encode(this.ticket, "UTF-8"));
try (CloseableHttpResponse response = httpClient.execute(request)) {
HttpEntity entity = response.getEntity();
String result = null;
if (entity != null) {
// return it as a String
result = EntityUtils.toString(entity);
if(result.replace("\n", "").trim().equals("no")){
throw new CasValidationExcepiton("Validation failed");
}
}
String res = result.substring(result.indexOf('\n') + 1);
return res;
}
}
}

View File

@ -0,0 +1,64 @@
package com.plannaplan.security;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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**").antMatchers("/api/v1/courses/getCourses")
.antMatchers("/api/v1/groups/getCourseGroups").antMatchers("/api/v1/courses/getCoursesWithGroups");
}
@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()
.anyRequest().authenticated();
}
AuthenticationFilter authenticationFilter() throws Exception {
final AuthenticationFilter filter = new AuthenticationFilter(PROTECTED_URLS);
filter.setAuthenticationManager(authenticationManager());
return filter;
}
@Bean
AuthenticationEntryPoint forbiddenEntryPoint() {
return new HttpStatusEntryPoint(HttpStatus.FORBIDDEN);
}
}

View File

@ -0,0 +1,40 @@
package com.plannaplan.security;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.Ignore;
import org.junit.Test;
public class CasValidatorTest {
@Test
@Ignore
public void shouldValidateTicket() {
//you need to privide fresh ticket to make this test pass that's why it is marked as ignored
CasValidator validator = new CasValidator("http://localhost:3000",
"ST-572267-cbgKrcJLd0tdCubeLqdW-cas.amu.edu.pl");
try {
System.out.println(validator.validate());
} catch (Exception e) {
e.printStackTrace();
assertTrue(false);
}
}
@Test
public void shouldNotValidateTicket() {
//you need to privide fresh ticket to make this test pass that's why it is marked as ignored
CasValidator validator = new CasValidator("http://localhost:3000",
"notticket");
try {
assertTrue(validator.validate().trim().equals(""));
}
catch (CasValidationExcepiton e){
assertTrue(true);
}
catch (Exception e) {
e.printStackTrace();
assertTrue(false);
}
}
}