Skip to content

Commit d20b551

Browse files
committed
configure auth
1 parent 6786773 commit d20b551

File tree

14 files changed

+357
-52
lines changed

14 files changed

+357
-52
lines changed

pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@
3333
<artifactId>spring-boot-starter-web</artifactId>
3434
</dependency>
3535

36+
<dependency>
37+
<groupId>io.jsonwebtoken</groupId>
38+
<artifactId>jjwt</artifactId>
39+
<version>0.9.1</version>
40+
</dependency>
41+
3642
<dependency>
3743
<groupId>com.oracle.database.jdbc</groupId>
3844
<artifactId>ojdbc8</artifactId>

src/main/java/ru/ifmo/web/SpringWeb/config/AuthConfiguration.java

Lines changed: 0 additions & 33 deletions
This file was deleted.
Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,38 @@
11
package ru.ifmo.web.SpringWeb.controller;
22

3+
import org.springframework.beans.factory.annotation.Autowired;
4+
import org.springframework.http.ResponseEntity;
35
import org.springframework.web.bind.annotation.*;
46
import ru.ifmo.web.SpringWeb.model.User;
5-
6-
import javax.servlet.http.HttpServletRequest;
7-
import java.security.Principal;
8-
import java.util.Base64;
7+
import ru.ifmo.web.SpringWeb.payload.AuthResponse;
8+
import ru.ifmo.web.SpringWeb.payload.ErrorResponse;
9+
import ru.ifmo.web.SpringWeb.payload.MessageResponse;
10+
import ru.ifmo.web.SpringWeb.security.JwtProvider;
11+
import ru.ifmo.web.SpringWeb.service.UserService;
912

1013
@RestController
1114
@CrossOrigin
1215
public class UserController {
1316

14-
@RequestMapping("/login")
15-
public boolean login(@RequestBody User user) {
16-
return user.getUsername().equals("user") && user.getPassword().equals("password");
17+
private final UserService userService;
18+
private final JwtProvider jwtProvider;
19+
20+
public UserController(UserService userService, JwtProvider jwtProvider) {
21+
this.userService = userService;
22+
this.jwtProvider = jwtProvider;
1723
}
1824

19-
@RequestMapping("/user")
20-
public Principal user(HttpServletRequest request) {
21-
String authToken = request.getHeader("Authorization")
22-
.substring("Basic".length()).trim();
23-
return () -> new String(Base64.getDecoder()
24-
.decode(authToken)).split(":")[0];
25+
@RequestMapping("/login")
26+
public ResponseEntity<?> login(@RequestBody User request) {
27+
User user = userService.findUserByUsernameAndPassword(request.getUsername(), request.getPassword());
28+
if(user != null){
29+
String token = jwtProvider.generateToken(request.getUsername());
30+
return ResponseEntity.ok(new AuthResponse(token));
31+
}
32+
33+
return ResponseEntity
34+
.badRequest()
35+
.body(new ErrorResponse("Incorrect username or password"));
2536
}
37+
2638
}

src/main/java/ru/ifmo/web/SpringWeb/model/Point.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
public class Point implements Serializable {
1212

1313
@Id
14-
@GeneratedValue(strategy = GenerationType.IDENTITY)
14+
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator = "id_Sequence")
15+
@SequenceGenerator(name = "id_Sequence", sequenceName = "ID_SEQ")
1516
private Long id;
1617

1718
private Integer x;

src/main/java/ru/ifmo/web/SpringWeb/model/User.java

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,30 @@
22

33

44
import lombok.Data;
5+
import lombok.Getter;
6+
import lombok.Setter;
7+
import org.springframework.security.core.GrantedAuthority;
8+
import org.springframework.security.core.userdetails.UserDetails;
59

610
import javax.persistence.*;
711
import java.io.Serializable;
12+
import java.util.Collection;
813

914
@Data
1015
@Entity
1116
@Table(name = "users")
12-
public class User implements Serializable {
17+
public class User implements Serializable, UserDetails {
1318

14-
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
15-
private final Long id;
19+
@Id
20+
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator = "id_Sequence")
21+
@SequenceGenerator(name = "id_Sequence", sequenceName = "ID_SEQ")
22+
private Long id;
1623

1724
@Column(nullable = false, unique = true)
18-
private final String username;
25+
private String username;
1926

2027
@Column(nullable = false)
21-
private final String password;
28+
private String password;
2229

2330
public User() {
2431
id = null;
@@ -31,4 +38,38 @@ public User(Long id, String username, String password) {
3138
this.username = username;
3239
this.password = password;
3340
}
41+
42+
@Override
43+
public String toString() {
44+
return "User{" +
45+
"id=" + id +
46+
", username='" + username + '\'' +
47+
", password='" + password + '\'' +
48+
'}';
49+
}
50+
51+
@Override
52+
public Collection<? extends GrantedAuthority> getAuthorities() {
53+
return null;
54+
}
55+
56+
@Override
57+
public boolean isAccountNonExpired() {
58+
return true;
59+
}
60+
61+
@Override
62+
public boolean isAccountNonLocked() {
63+
return true;
64+
}
65+
66+
@Override
67+
public boolean isCredentialsNonExpired() {
68+
return true;
69+
}
70+
71+
@Override
72+
public boolean isEnabled() {
73+
return true;
74+
}
3475
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package ru.ifmo.web.SpringWeb.payload;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Data;
5+
6+
@Data
7+
@AllArgsConstructor
8+
public class AuthResponse {
9+
10+
private String token;
11+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package ru.ifmo.web.SpringWeb.payload;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Data;
5+
6+
@Data
7+
@AllArgsConstructor
8+
public class ErrorResponse {
9+
private String error;
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package ru.ifmo.web.SpringWeb.payload;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Data;
5+
6+
@Data
7+
@AllArgsConstructor
8+
public class MessageResponse {
9+
private String message;
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package ru.ifmo.web.SpringWeb.repository;
2+
3+
import org.springframework.data.jpa.repository.JpaRepository;
4+
import ru.ifmo.web.SpringWeb.model.Point;
5+
6+
public interface PointRepository extends JpaRepository<Point, Long> {
7+
void deleteAll();
8+
void deleteAllById(Long id);
9+
10+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package ru.ifmo.web.SpringWeb.repository;
2+
3+
import org.springframework.data.jpa.repository.JpaRepository;
4+
import ru.ifmo.web.SpringWeb.model.User;
5+
6+
public interface UserRepository extends JpaRepository<User, Long> {
7+
User findByUsername(String username);
8+
User findByUsernameAndPassword(String username, String password);
9+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package ru.ifmo.web.SpringWeb.security;
2+
3+
import org.springframework.beans.factory.annotation.Autowired;
4+
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
5+
import org.springframework.security.core.context.SecurityContextHolder;
6+
import org.springframework.security.core.userdetails.UserDetails;
7+
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
8+
import org.springframework.util.StringUtils;
9+
import org.springframework.web.filter.OncePerRequestFilter;
10+
import ru.ifmo.web.SpringWeb.service.UserService;
11+
12+
import javax.servlet.FilterChain;
13+
import javax.servlet.ServletException;
14+
import javax.servlet.http.HttpServletRequest;
15+
import javax.servlet.http.HttpServletResponse;
16+
import java.io.IOException;
17+
18+
public class JwtFilter extends OncePerRequestFilter {
19+
20+
@Autowired
21+
private JwtProvider jwtProvider;
22+
23+
@Autowired
24+
private UserService userService;
25+
26+
@Override
27+
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
28+
29+
try {
30+
String jwt = parseJwt(httpServletRequest);
31+
if (jwt != null && jwtProvider.validateToken(jwt)) {
32+
String username = jwtProvider.getLoginFromToken(jwt);
33+
34+
UserDetails userDetails = userService.loadUserByUsername(username);
35+
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
36+
userDetails, null, userDetails.getAuthorities());
37+
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpServletRequest));
38+
39+
SecurityContextHolder.getContext().setAuthentication(authentication);
40+
}
41+
} catch (Exception e) {
42+
System.err.println("Cannot set user authentication: " + e);
43+
}
44+
45+
filterChain.doFilter(httpServletRequest, httpServletResponse);
46+
}
47+
48+
49+
private String parseJwt(HttpServletRequest request) {
50+
String headerAuth = request.getHeader("Authorization");
51+
52+
if (StringUtils.hasText(headerAuth) && headerAuth.startsWith("Bearer ")) {
53+
return headerAuth.substring(7, headerAuth.length());
54+
}
55+
56+
return null;
57+
}
58+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package ru.ifmo.web.SpringWeb.security;
2+
3+
import io.jsonwebtoken.Claims;
4+
import io.jsonwebtoken.Jwts;
5+
import io.jsonwebtoken.SignatureAlgorithm;
6+
import org.springframework.beans.factory.annotation.Value;
7+
import org.springframework.stereotype.Component;
8+
9+
import java.time.LocalDate;
10+
import java.time.ZoneId;
11+
import java.util.Date;
12+
13+
@Component
14+
public class JwtProvider {
15+
16+
@Value("$(jwt.secret)")
17+
private String jwtSecret;
18+
19+
public String generateToken(String login) {
20+
Date date = Date.from(LocalDate.now().plusDays(15).atStartOfDay(ZoneId.systemDefault()).toInstant());
21+
return Jwts.builder()
22+
.setSubject(login)
23+
.setExpiration(date)
24+
.signWith(SignatureAlgorithm.HS512, jwtSecret)
25+
.compact();
26+
}
27+
28+
public boolean validateToken(String token) {
29+
try {
30+
Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token);
31+
return true;
32+
} catch (Exception ex) {
33+
System.err.println("Token expired");
34+
}
35+
36+
return false;
37+
}
38+
39+
public String getLoginFromToken(String token) {
40+
Claims claims = Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token).getBody();
41+
return claims.getSubject();
42+
}
43+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package ru.ifmo.web.SpringWeb.security.config;
2+
3+
import org.springframework.beans.factory.annotation.Autowired;
4+
import org.springframework.context.annotation.Bean;
5+
import org.springframework.context.annotation.Configuration;
6+
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
7+
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
8+
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
9+
import org.springframework.security.config.http.SessionCreationPolicy;
10+
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
11+
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
12+
import ru.ifmo.web.SpringWeb.security.JwtFilter;
13+
import ru.ifmo.web.SpringWeb.service.UserService;
14+
15+
@Configuration
16+
@EnableWebSecurity
17+
public class AuthConfiguration extends WebSecurityConfigurerAdapter {
18+
19+
@Autowired
20+
UserService userService;
21+
22+
@Bean
23+
public BCryptPasswordEncoder bCryptPasswordEncoder() {
24+
return new BCryptPasswordEncoder();
25+
}
26+
27+
@Bean
28+
public JwtFilter authJwtFilter() {
29+
return new JwtFilter();
30+
}
31+
32+
33+
34+
@Override
35+
protected void configure(HttpSecurity httpSecurity) throws Exception {
36+
httpSecurity
37+
.httpBasic().disable()
38+
.csrf().disable()
39+
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
40+
.and()
41+
.authorizeRequests()
42+
.antMatchers("/register", "/login").permitAll()
43+
.anyRequest().authenticated()
44+
.and()
45+
.addFilterBefore(authJwtFilter(), UsernamePasswordAuthenticationFilter.class);
46+
}
47+
48+
}

0 commit comments

Comments
 (0)