fin
This commit is contained in:
parent
e67fa9e3f2
commit
2006d34fd5
@ -33,6 +33,13 @@ dependencies {
|
||||
implementation 'org.webjars:jquery:3.7.1'
|
||||
// https://mvnrepository.com/artifact/org.webjars/popper.js
|
||||
implementation 'org.webjars:popper.js:2.11.7'
|
||||
implementation "org.springframework.boot:spring-boot-starter-security"
|
||||
// https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-impl
|
||||
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.6'
|
||||
// https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-api
|
||||
implementation 'io.jsonwebtoken:jjwt-api:0.12.6'
|
||||
// https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-jackson
|
||||
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.6'
|
||||
|
||||
|
||||
}
|
||||
|
10
front/package-lock.json
generated
10
front/package-lock.json
generated
@ -10,6 +10,7 @@
|
||||
"dependencies": {
|
||||
"axios": "^1.4.0",
|
||||
"bootstrap": "^5.2.3",
|
||||
"jwt-decode": "^4.0.0",
|
||||
"vue": "^3.2.47",
|
||||
"vue-multiselect": "^3.0.0-beta.3",
|
||||
"vue-router": "^4.2.2"
|
||||
@ -662,6 +663,15 @@
|
||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/jwt-decode": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz",
|
||||
"integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/magic-string": {
|
||||
"version": "0.30.0",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.0.tgz",
|
||||
|
@ -11,6 +11,7 @@
|
||||
"dependencies": {
|
||||
"axios": "^1.4.0",
|
||||
"bootstrap": "^5.2.3",
|
||||
"jwt-decode": "^4.0.0",
|
||||
"vue": "^3.2.47",
|
||||
"vue-multiselect": "^3.0.0-beta.3",
|
||||
"vue-router": "^4.2.2"
|
||||
|
@ -22,7 +22,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="account clickable-element py-4 ml-auto">
|
||||
<router-link to="/account">
|
||||
<router-link :to="{name: 'Account'}">
|
||||
<img src="../assets/header/account.png">
|
||||
</router-link>
|
||||
</div>
|
||||
|
19
front/src/pages/Account.vue
Normal file
19
front/src/pages/Account.vue
Normal file
@ -0,0 +1,19 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1>Аккаунт</h1>
|
||||
<button @click="logout" class="btn btn-danger">Log Out</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {removeToken} from "../services/userService";
|
||||
|
||||
export default {
|
||||
methods: {
|
||||
logout() {
|
||||
removeToken();
|
||||
this.$router.push("/login");
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
34
front/src/pages/Error401.vue
Normal file
34
front/src/pages/Error401.vue
Normal file
@ -0,0 +1,34 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 text-center">
|
||||
<h1>Доступ запрещен</h1>
|
||||
<p>У вас нет прав на доступ к этому ресурсу. Пожалуйста, обратитесь к администратору.</p>
|
||||
<router-link :to="{name: 'Home'}" class="btn btn-primary">Вернуться на главную</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.container {
|
||||
margin-top: 100px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 144px;
|
||||
line-height: 100px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 48px;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
font-size: 24px;
|
||||
}
|
||||
</style>
|
52
front/src/pages/Login.vue
Normal file
52
front/src/pages/Login.vue
Normal file
@ -0,0 +1,52 @@
|
||||
<template>
|
||||
<div>
|
||||
<h1 class="m-3 ms-sm-4">ЛОГИН</h1>
|
||||
<form @submit.prevent="login" class="m-3">
|
||||
<div class="mb-3">
|
||||
<label for="username" class="form-label">Логин</label>
|
||||
<input type="text" class="form-control" id="username" v-model="username" required autofocus>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="password" class="form-label">Пароль</label>
|
||||
<input type="password" class="form-control" id="password" v-model="password" required>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">ВОЙТИ</button>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {setToken} from "../services/userService";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
username: '',
|
||||
password: '',
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async login() {
|
||||
const userData = {
|
||||
username: this.username,
|
||||
password: this.password
|
||||
};
|
||||
fetch('http://localhost:8080/api/auth', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(userData)
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
setToken(data.token);
|
||||
this.$router.push('/');
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@ -1,21 +1,27 @@
|
||||
import {createRouter, createWebHistory} from 'vue-router'
|
||||
import Home from './pages/Home.vue'
|
||||
import Film from './pages/Film.vue'
|
||||
|
||||
import {createRouter, createWebHistory} from 'vue-router'
|
||||
import CountriesManager from "./pages/CountriesManager.vue";
|
||||
import GenresManager from "./pages/GenresManager.vue";
|
||||
import TeamPositionsManager from "./pages/TeamPositionsManager.vue";
|
||||
import MembersManager from "./pages/MembersManager.vue";
|
||||
import FilmsManager from "./pages/FilmsManager.vue";
|
||||
import Login from './pages/Login.vue';
|
||||
import axios from 'axios';
|
||||
import Error401 from './pages/Error401.vue';
|
||||
import Account from './pages/Account.vue';
|
||||
|
||||
const routes = [
|
||||
{ path: "/", component: Home, name: "Home" },
|
||||
{ path: "/films/:id", component: Film, name: "Film" },
|
||||
{ path: "/countries/manager", component: CountriesManager, name: "CountriesManager" },
|
||||
{ path: "/genres/manager", component: GenresManager, name: "GenresManager" },
|
||||
{ path: "/team_positions/manager", component: TeamPositionsManager, name: "TeamPositionsManager" },
|
||||
{ path: "/members/manager", component: MembersManager, name: "MembersManager" },
|
||||
{ path: "/films/manager", component: FilmsManager, name: "FilmManager" }
|
||||
{ path: "/", component: Home, name: "Home", meta: { requiresAuth: true } },
|
||||
{ path: "/films/:id", component: Film, name: "Film", meta: { requiresAuth: true } },
|
||||
{ path: "/countries/manager", component: CountriesManager, name: "CountriesManager", meta: { requiresAuth: true, requiresAdmin: true } },
|
||||
{ path: "/genres/manager", component: GenresManager, name: "GenresManager", meta: { requiresAuth: true, requiresAdmin: true } },
|
||||
{ path: "/team_positions/manager", component: TeamPositionsManager, name: "TeamPositionsManager", meta: { requiresAuth: true, requiresAdmin: true } },
|
||||
{ path: "/members/manager", component: MembersManager, name: "MembersManager", meta: { requiresAuth: true, requiresAdmin: true } },
|
||||
{ path: "/films/manager", component: FilmsManager, name: "FilmManager", meta: { requiresAuth: true, requiresAdmin: true } },
|
||||
{ path: "/login", component: Login, name: "Login", meta: { requiresAuth: false } },
|
||||
{ path: "/account", component: Account, name: "Account", meta: { requiresAuth: true } },
|
||||
{ path: "/401", component: Error401, name: "401", meta: { requiresAuth: false } }
|
||||
]
|
||||
|
||||
const router = new createRouter({
|
||||
@ -23,4 +29,14 @@ const router = new createRouter({
|
||||
routes: routes
|
||||
})
|
||||
|
||||
router.beforeEach((to, from, next) => {
|
||||
if (to.meta.requiresAuth && !axios.defaults.headers.common["Authorization"]) {
|
||||
next({ name: 'Login' })
|
||||
} else if (to.meta.requiresAdmin && !sessionStorage.getItem("roles").includes("ROLE_ADMIN")) {
|
||||
next({ name: '401' })
|
||||
} else {
|
||||
next()
|
||||
}
|
||||
})
|
||||
|
||||
export default router
|
||||
|
6
front/src/services/jwtService.js
Normal file
6
front/src/services/jwtService.js
Normal file
@ -0,0 +1,6 @@
|
||||
import {jwtDecode} from "jwt-decode";
|
||||
export function getRolesFromToken(token) {
|
||||
const decodedToken = jwtDecode(token);
|
||||
const rolesClaim = decodedToken["roles"];
|
||||
return rolesClaim.split(" ");
|
||||
}
|
16
front/src/services/userService.js
Normal file
16
front/src/services/userService.js
Normal file
@ -0,0 +1,16 @@
|
||||
import {getRolesFromToken} from '../services/JwtService';
|
||||
import axios from 'axios';
|
||||
|
||||
export function setToken(token) {
|
||||
axios.defaults.headers.common["Authorization"] = `Bearer ${token}`;
|
||||
sessionStorage.setItem("roles", getRolesFromToken(token));
|
||||
}
|
||||
|
||||
export function removeToken() {
|
||||
axios.defaults.headers.common["Authorization"] = null;
|
||||
sessionStorage.removeItem("roles");
|
||||
}
|
||||
|
||||
export function isAuthorized() {
|
||||
return axios.defaults.headers.common["Authorization"] != null;
|
||||
}
|
@ -3,6 +3,7 @@ package com.ip.lab.DataBase.Country.Controller;
|
||||
import com.ip.lab.DataBase.Country.Service.CountryService;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.annotation.Secured;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -2,6 +2,8 @@ package com.ip.lab.DataBase.Country.Controller;
|
||||
|
||||
import com.ip.lab.DataBase.Country.Service.CountryService;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.security.access.annotation.Secured;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@ -10,6 +12,7 @@ import java.util.List;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/countries")
|
||||
@PreAuthorize("hasAuthority('ROLE_ADMIN')")
|
||||
public class CountryMVCController {
|
||||
private final CountryService service;
|
||||
|
||||
@ -26,6 +29,7 @@ public class CountryMVCController {
|
||||
.toList());
|
||||
return "countries/index";
|
||||
}
|
||||
|
||||
@GetMapping("/{id}/edit")
|
||||
public String editCountry(@PathVariable Long id, Model model) {
|
||||
model.addAttribute("country", new CountryDTO(service.get(id)));
|
||||
|
@ -10,6 +10,7 @@ import com.ip.lab.DataBase.Member.Controller.MemberDTO;
|
||||
import com.ip.lab.DataBase.Member.Model.Member;
|
||||
import com.ip.lab.DataBase.TeamPosition.Controller.TeamPositionDTO;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.security.access.annotation.Secured;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -13,6 +13,7 @@ import com.ip.lab.DataBase.Member.Service.MemberService;
|
||||
import com.ip.lab.DataBase.TeamPosition.Controller.TeamPositionDTO;
|
||||
import com.ip.lab.DataBase.TeamPosition.Service.TeamPositionService;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@ -22,6 +23,7 @@ import java.util.List;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/films")
|
||||
@PreAuthorize("hasAuthority('ROLE_ADMIN')")
|
||||
public class FilmMVCController {
|
||||
final FilmService service;
|
||||
final FilmMemberTeamPosService fmtpService;
|
||||
@ -42,6 +44,7 @@ public class FilmMVCController {
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
@PreAuthorize("hasAuthority('ROLE_USER') || hasAuthority('ROLE_USER')")
|
||||
public String getFilmById(@PathVariable Long id, Model model) {
|
||||
model.addAttribute("film", new FilmDTO(service.get(id)));
|
||||
model.addAttribute("teamMembers",
|
||||
|
@ -3,6 +3,7 @@ package com.ip.lab.DataBase.Genre.Controller;
|
||||
import com.ip.lab.DataBase.Country.Controller.CountryDTO;
|
||||
import com.ip.lab.DataBase.Genre.Service.GenreService;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.security.access.annotation.Secured;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -2,6 +2,7 @@ package com.ip.lab.DataBase.Genre.Controller;
|
||||
|
||||
import com.ip.lab.DataBase.Genre.Service.GenreService;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@ -10,6 +11,7 @@ import java.util.List;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/genres")
|
||||
@PreAuthorize("hasAuthority('ROLE_ADMIN')")
|
||||
public class GenreMVCController {
|
||||
final GenreService service;
|
||||
|
||||
|
61
src/main/java/com/ip/lab/DataBase/Jwt/JwtAuthFilter.java
Normal file
61
src/main/java/com/ip/lab/DataBase/Jwt/JwtAuthFilter.java
Normal file
@ -0,0 +1,61 @@
|
||||
package com.ip.lab.DataBase.Jwt;
|
||||
|
||||
import com.ip.lab.DataBase.User.Model.User;
|
||||
import com.ip.lab.DataBase.User.Service.UserService;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class JwtAuthFilter extends OncePerRequestFilter {
|
||||
@Autowired
|
||||
JwtService jwtService;
|
||||
@Autowired
|
||||
UserService userService;
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
String token = getTokenFromRequest(request);
|
||||
|
||||
// Валидируем токен
|
||||
if(StringUtils.hasText(token) && jwtService.validateToken(token)){
|
||||
String username = jwtService.getUsername(token);
|
||||
|
||||
User user = (User)userService.loadUserByUsername(username);
|
||||
|
||||
var authenticationToken = new UsernamePasswordAuthenticationToken(
|
||||
user,
|
||||
null,
|
||||
user.getAuthorities()
|
||||
);
|
||||
|
||||
var details = new WebAuthenticationDetailsSource().buildDetails(request);
|
||||
authenticationToken.setDetails(details);
|
||||
|
||||
SecurityContextHolder
|
||||
.getContext()
|
||||
.setAuthentication(authenticationToken);
|
||||
}
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
|
||||
private String getTokenFromRequest(HttpServletRequest request){
|
||||
String bearerToken = request.getHeader("Authorization");
|
||||
|
||||
if(!StringUtils.hasText(bearerToken) || !bearerToken.startsWith("Bearer ")){
|
||||
return null;
|
||||
}
|
||||
return bearerToken.substring(7, bearerToken.length());
|
||||
}
|
||||
}
|
19
src/main/java/com/ip/lab/DataBase/Jwt/JwtAuthResponse.java
Normal file
19
src/main/java/com/ip/lab/DataBase/Jwt/JwtAuthResponse.java
Normal file
@ -0,0 +1,19 @@
|
||||
package com.ip.lab.DataBase.Jwt;
|
||||
|
||||
|
||||
public class JwtAuthResponse {
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
public void setToken(String token) {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
private String token;
|
||||
|
||||
public JwtAuthResponse() {}
|
||||
public JwtAuthResponse(String token) {
|
||||
this.token = token;
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package com.ip.lab.DataBase.Jwt;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@Component
|
||||
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
|
||||
@Override
|
||||
public void commence(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
AuthenticationException authException) throws IOException, ServletException {
|
||||
|
||||
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage());
|
||||
}
|
||||
}
|
59
src/main/java/com/ip/lab/DataBase/Jwt/JwtService.java
Normal file
59
src/main/java/com/ip/lab/DataBase/Jwt/JwtService.java
Normal file
@ -0,0 +1,59 @@
|
||||
package com.ip.lab.DataBase.Jwt;
|
||||
|
||||
import com.ip.lab.DataBase.Role.Model.Role;
|
||||
import com.ip.lab.DataBase.User.Model.User;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.security.Keys;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class JwtService {
|
||||
@Value("${jwt.secret}")
|
||||
private String secret;
|
||||
|
||||
public String generateToken(User user) {
|
||||
var key = getKey();
|
||||
// 10 часов
|
||||
Date expireDate = new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10);
|
||||
var badToken = Jwts.builder()
|
||||
.subject(user.getUsername())
|
||||
.expiration(expireDate)
|
||||
.issuedAt(new Date())
|
||||
.claim("roles", user.getStringRoles())
|
||||
.signWith(key);
|
||||
var token = badToken.compact();
|
||||
return token;
|
||||
}
|
||||
|
||||
private SecretKey getKey() {
|
||||
return Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
public boolean validateToken(String token) {
|
||||
try {
|
||||
Jwts.parser()
|
||||
.verifyWith(getKey())
|
||||
.build()
|
||||
.parse(token);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public String getUsername(String token) {
|
||||
return Jwts.parser()
|
||||
.verifyWith(getKey())
|
||||
.build()
|
||||
.parseSignedClaims(token)
|
||||
.getPayload()
|
||||
.getSubject();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package com.ip.lab.DataBase.Main.Controller;
|
||||
|
||||
import com.ip.lab.DataBase.Jwt.JwtAuthResponse;
|
||||
import com.ip.lab.DataBase.Main.Service.AuthenticationService;
|
||||
import com.ip.lab.DataBase.User.Controller.UserDTO;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/auth")
|
||||
public class AuthenticationController {
|
||||
@Autowired
|
||||
AuthenticationService authService;
|
||||
|
||||
@PostMapping
|
||||
public JwtAuthResponse login(@RequestBody UserDTO user) {
|
||||
String token = authService.login(user.toUser());
|
||||
|
||||
return new JwtAuthResponse(token);
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package com.ip.lab.DataBase.Main.Service;
|
||||
|
||||
import com.ip.lab.DataBase.Jwt.JwtService;
|
||||
import com.ip.lab.DataBase.User.Model.User;
|
||||
import com.ip.lab.DataBase.User.Service.UserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class AuthenticationService {
|
||||
|
||||
@Autowired
|
||||
JwtService jwtService;
|
||||
@Autowired
|
||||
UserService userService;
|
||||
|
||||
|
||||
|
||||
public String login(User user) {
|
||||
var fullDataUser = (User)userService.loadUserByUsername(user.getUsername());
|
||||
|
||||
return jwtService.generateToken(fullDataUser);
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ package com.ip.lab.DataBase.Member.Controller;
|
||||
import com.ip.lab.DataBase.Country.Controller.CountryDTO;
|
||||
import com.ip.lab.DataBase.Member.Service.MemberService;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.security.access.annotation.Secured;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -2,6 +2,7 @@ package com.ip.lab.DataBase.Member.Controller;
|
||||
|
||||
import com.ip.lab.DataBase.Member.Service.MemberService;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@ -10,6 +11,7 @@ import java.util.List;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/members")
|
||||
@PreAuthorize("hasAuthority('ROLE_ADMIN')")
|
||||
public class MemberMVCController {
|
||||
final MemberService service;
|
||||
|
||||
|
@ -0,0 +1,41 @@
|
||||
package com.ip.lab.DataBase.Role.Controller;
|
||||
|
||||
import com.ip.lab.DataBase.Role.Service.RoleService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/roles")
|
||||
public class RoleController {
|
||||
@Autowired
|
||||
RoleService roleService;
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public RoleDTO getRoleById(@PathVariable Long id) {
|
||||
return new RoleDTO(roleService.get(id));
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public List<RoleDTO> getAllRoles() {
|
||||
return roleService.getAll().stream().map(RoleDTO::new).toList();
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public RoleDTO createRole(@RequestBody RoleDTO roleDTO) {
|
||||
return new RoleDTO(roleService.add(roleDTO.toRole()));
|
||||
}
|
||||
|
||||
@PutMapping
|
||||
public RoleDTO updateRole(@RequestBody RoleDTO roleDTO) {
|
||||
return new RoleDTO(roleService.update(roleDTO.getId(), roleDTO.toRole()));
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
public RoleDTO deleteRole(@PathVariable Long id) {
|
||||
return new RoleDTO(roleService.remove(id));
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package com.ip.lab.DataBase.Role.Controller;
|
||||
|
||||
import com.ip.lab.DataBase.Role.Model.Role;
|
||||
|
||||
public class RoleDTO {
|
||||
|
||||
private Long id;
|
||||
private String name;
|
||||
|
||||
public RoleDTO() {}
|
||||
public RoleDTO(Role role) {
|
||||
this.id = role.getId();
|
||||
this.name = role.getName();
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Role toRole() {
|
||||
Role role = new Role();
|
||||
role.setId(id);
|
||||
role.setName(name);
|
||||
return role;
|
||||
}
|
||||
}
|
51
src/main/java/com/ip/lab/DataBase/Role/Model/Role.java
Normal file
51
src/main/java/com/ip/lab/DataBase/Role/Model/Role.java
Normal file
@ -0,0 +1,51 @@
|
||||
package com.ip.lab.DataBase.Role.Model;
|
||||
|
||||
import com.ip.lab.DataBase.User.Model.User;
|
||||
import jakarta.persistence.*;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
public class Role implements GrantedAuthority {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long id;
|
||||
private String name;
|
||||
@ManyToMany(mappedBy = "roles")
|
||||
private List<User> users;
|
||||
|
||||
public Role() {}
|
||||
public Role(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<User> getUsers() {
|
||||
return users;
|
||||
}
|
||||
|
||||
public void setUsers(List<User> users) {
|
||||
this.users = users;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthority() {
|
||||
return getName();
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package com.ip.lab.DataBase.Role.Repository;
|
||||
|
||||
import com.ip.lab.DataBase.Role.Model.Role;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface IRoleRepository extends JpaRepository<Role, Long> {
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package com.ip.lab.DataBase.Role.Service;
|
||||
|
||||
import com.ip.lab.DataBase.Interfaces.ICRUDService;
|
||||
import com.ip.lab.DataBase.Role.Model.Role;
|
||||
import com.ip.lab.DataBase.Role.Repository.IRoleRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class RoleService implements ICRUDService<Role> {
|
||||
final IRoleRepository repository;
|
||||
|
||||
public RoleService(IRoleRepository repository) {
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Role get(Long id) {
|
||||
return repository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Role> getAll() {
|
||||
return repository.findAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Role remove(Long id) {
|
||||
Role role = get(id);
|
||||
if (role != null) {
|
||||
repository.deleteById(id);
|
||||
}
|
||||
return role;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAll() {
|
||||
repository.deleteAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Role add(Role entity) {
|
||||
return repository.save(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Role update(Long id, Role newEntity) {
|
||||
Role role = get(id);
|
||||
if (role != null) {
|
||||
role.setName(newEntity.getName());
|
||||
return repository.save(role);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ package com.ip.lab.DataBase.TeamPosition.Controller;
|
||||
import com.ip.lab.DataBase.Country.Controller.CountryDTO;
|
||||
import com.ip.lab.DataBase.TeamPosition.Service.TeamPositionService;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.security.access.annotation.Secured;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -2,6 +2,7 @@ package com.ip.lab.DataBase.TeamPosition.Controller;
|
||||
|
||||
import com.ip.lab.DataBase.TeamPosition.Service.TeamPositionService;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@ -10,6 +11,7 @@ import java.util.List;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/team-positions")
|
||||
@PreAuthorize("hasAuthority('ROLE_ADMIN')")
|
||||
public class TeamPositionMVCController {
|
||||
|
||||
final TeamPositionService service;
|
||||
|
@ -0,0 +1,39 @@
|
||||
package com.ip.lab.DataBase.User.Controller;
|
||||
|
||||
import com.ip.lab.DataBase.User.Service.UserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/users")
|
||||
public class UserController {
|
||||
@Autowired
|
||||
UserService userService;
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public UserDTO getUserById(@PathVariable Long id) {
|
||||
return new UserDTO(userService.get(id));
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public List<UserDTO> getAllUsers() {
|
||||
return userService.getAll().stream().map(UserDTO::new).toList();
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public UserDTO createUser(@RequestBody UserDTO userDTO) {
|
||||
return new UserDTO(userService.add(userDTO.toUser()));
|
||||
}
|
||||
|
||||
@PutMapping
|
||||
public UserDTO updateUser(@RequestBody UserDTO userDTO) {
|
||||
return new UserDTO(userService.update(userDTO.getId(), userDTO.toUser()));
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
public UserDTO deleteUser(@PathVariable Long id) {
|
||||
return new UserDTO(userService.remove(id));
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
package com.ip.lab.DataBase.User.Controller;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.ip.lab.DataBase.Role.Controller.RoleDTO;
|
||||
import com.ip.lab.DataBase.User.Model.User;
|
||||
|
||||
public class UserDTO {
|
||||
private Long id;
|
||||
private String username;
|
||||
private String password;
|
||||
private List<RoleDTO> roles;
|
||||
|
||||
public UserDTO() {}
|
||||
|
||||
public UserDTO(User user) {
|
||||
this.id = user.getId();
|
||||
this.username = user.getUsername();
|
||||
this.password = user.getPassword();
|
||||
this.roles = user.getRoles().stream().map(RoleDTO::new).toList();
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public List<RoleDTO> getRoles() {
|
||||
return roles;
|
||||
}
|
||||
|
||||
public void setRoles(List<RoleDTO> roles) {
|
||||
this.roles = new ArrayList<>(roles);
|
||||
}
|
||||
|
||||
public User toUser() {
|
||||
User user = new User();
|
||||
if (id != null) {
|
||||
user.setId(id);
|
||||
}
|
||||
if (username != null) {
|
||||
user.setUsername(username);
|
||||
}
|
||||
if (password != null) {
|
||||
user.setPassword(password);
|
||||
}
|
||||
if (roles != null) {
|
||||
user.setRoles(roles.stream().map(RoleDTO::toRole).toList());
|
||||
}
|
||||
return user;
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package com.ip.lab.DataBase.User.Controller;
|
||||
|
||||
import com.ip.lab.DataBase.User.Service.UserService;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/user")
|
||||
public class UserMVCController {
|
||||
final UserService userService;
|
||||
|
||||
public UserMVCController(UserService userService) {
|
||||
this.userService = userService;
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public String getUser(Model model, Long id) {
|
||||
model.addAttribute("user", new UserDTO(userService.get(id)));
|
||||
return "users/index";
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public String createUser(@ModelAttribute @Valid UserDTO userDTO, Model model) {
|
||||
userService.add(userDTO.toUser());
|
||||
return "redirect:/user";
|
||||
}
|
||||
}
|
90
src/main/java/com/ip/lab/DataBase/User/Model/User.java
Normal file
90
src/main/java/com/ip/lab/DataBase/User/Model/User.java
Normal file
@ -0,0 +1,90 @@
|
||||
package com.ip.lab.DataBase.User.Model;
|
||||
|
||||
import com.ip.lab.DataBase.Role.Model.Role;
|
||||
import jakarta.persistence.*;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Entity
|
||||
@Table(name = "t_users")
|
||||
public class User implements UserDetails {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE)
|
||||
private Long id;
|
||||
private String username;
|
||||
private String password;
|
||||
@ManyToMany(fetch = FetchType.EAGER)
|
||||
private List<Role> roles;
|
||||
|
||||
public User() {}
|
||||
public User(String password, String username) {
|
||||
this.password = password;
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccountNonExpired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccountNonLocked() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCredentialsNonExpired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||
return getRoles();
|
||||
}
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public List<Role> getRoles() {
|
||||
return roles;
|
||||
}
|
||||
|
||||
public void setRoles(List<Role> roles) {
|
||||
this.roles = roles;
|
||||
}
|
||||
|
||||
public String getStringRoles() {
|
||||
return roles.stream().map(Role::getName).collect(Collectors.joining(" "));
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package com.ip.lab.DataBase.User.Repository;
|
||||
|
||||
import com.ip.lab.DataBase.User.Model.User;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
public interface IUserRepository extends JpaRepository<User, Long> {
|
||||
User findByUsername(String username);
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
package com.ip.lab.DataBase.User.Service;
|
||||
|
||||
import com.ip.lab.DataBase.Interfaces.ICRUDService;
|
||||
import com.ip.lab.DataBase.Role.Model.Role;
|
||||
import com.ip.lab.DataBase.User.Controller.UserDTO;
|
||||
import com.ip.lab.DataBase.User.Model.User;
|
||||
import com.ip.lab.DataBase.User.Repository.IUserRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class UserService implements UserDetailsService {
|
||||
@Autowired
|
||||
IUserRepository repository;
|
||||
@Autowired
|
||||
BCryptPasswordEncoder bCryptPasswordEncoder;
|
||||
|
||||
|
||||
|
||||
public User get(Long id) {
|
||||
return repository.findById(id).orElse(null);
|
||||
}
|
||||
|
||||
|
||||
public List<User> getAll() {
|
||||
return repository.findAll();
|
||||
}
|
||||
|
||||
|
||||
public User remove(Long id) {
|
||||
User user = get(id);
|
||||
if (user != null) {
|
||||
repository.delete(user);
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
|
||||
public void removeAll() {
|
||||
repository.deleteAll();
|
||||
}
|
||||
|
||||
|
||||
public User add(User entity) {
|
||||
User userFromDB = repository.findByUsername(entity.getUsername());
|
||||
|
||||
if (userFromDB != null) {
|
||||
return null;
|
||||
}
|
||||
if (entity.getRoles().isEmpty()) {
|
||||
var role = new Role("ROLE_USER");
|
||||
entity.setRoles(new ArrayList<>(Collections.singleton(role)));
|
||||
}
|
||||
entity.setPassword(bCryptPasswordEncoder.encode(entity.getPassword()));
|
||||
return repository.save(entity);
|
||||
}
|
||||
|
||||
public User update(Long id, User newEntity) {
|
||||
User user = get(id);
|
||||
if (user != null) {
|
||||
user.setUsername(newEntity.getUsername());
|
||||
user.setPassword(newEntity.getPassword());
|
||||
user.setRoles(newEntity.getRoles());
|
||||
return repository.save(user);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
var user = repository.findByUsername(username);
|
||||
|
||||
if (user == null) {
|
||||
throw new UsernameNotFoundException("User not found");
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
@Configuration
|
||||
public class WebConfiguration implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
public void addCorsMappings(CorsRegistry registry) {
|
||||
registry.addMapping("/**").allowedMethods("*");
|
||||
|
16
src/main/java/com/ip/lab/WebMVCConfiguration.java
Normal file
16
src/main/java/com/ip/lab/WebMVCConfiguration.java
Normal file
@ -0,0 +1,16 @@
|
||||
package com.ip.lab;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
@Configuration
|
||||
public class WebMVCConfiguration implements WebMvcConfigurer {
|
||||
@Override
|
||||
public void addViewControllers(ViewControllerRegistry registry) {
|
||||
registry.addViewController("/login").setViewName("login");
|
||||
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
|
||||
}
|
||||
}
|
79
src/main/java/com/ip/lab/WebSecurityConfig.java
Normal file
79
src/main/java/com/ip/lab/WebSecurityConfig.java
Normal file
@ -0,0 +1,79 @@
|
||||
package com.ip.lab;
|
||||
|
||||
import com.ip.lab.DataBase.Jwt.JwtAuthFilter;
|
||||
import com.ip.lab.DataBase.Jwt.JwtAuthenticationEntryPoint;
|
||||
import com.ip.lab.DataBase.User.Service.UserService;
|
||||
import jakarta.servlet.DispatcherType;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.security.web.server.SecurityWebFilterChain;
|
||||
|
||||
@EnableWebSecurity
|
||||
@Configuration
|
||||
@EnableMethodSecurity
|
||||
public class WebSecurityConfig {
|
||||
@Autowired
|
||||
JwtAuthenticationEntryPoint authenticationEntryPoint;
|
||||
|
||||
@Bean
|
||||
public JwtAuthFilter jwtAuthFilter() {
|
||||
return new JwtAuthFilter();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public BCryptPasswordEncoder bCryptPasswordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public UserDetailsService userDetailsService() {
|
||||
return new UserService();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
http.cors().and().csrf().disable();
|
||||
http.authorizeHttpRequests(auth -> auth
|
||||
.requestMatchers("/swagger-ui/**").permitAll()
|
||||
.requestMatchers("/v3/api-docs/**").permitAll()
|
||||
.requestMatchers(HttpMethod.GET, "/api/**").permitAll()
|
||||
.requestMatchers(HttpMethod.POST, "/api/auth").permitAll()
|
||||
.requestMatchers("/api/**").hasRole("ADMIN")
|
||||
.anyRequest().authenticated()
|
||||
);
|
||||
|
||||
http.formLogin()
|
||||
.loginPage("/login")
|
||||
.permitAll();
|
||||
http.logout().permitAll();
|
||||
|
||||
http.userDetailsService(userDetailsService());
|
||||
|
||||
http.exceptionHandling( exception -> exception
|
||||
.authenticationEntryPoint(authenticationEntryPoint));
|
||||
|
||||
http.addFilterBefore(jwtAuthFilter(), UsernamePasswordAuthenticationFilter.class);
|
||||
return http.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public WebSecurityCustomizer webSecurityCustomizer() {
|
||||
return (web) -> web.ignoring().requestMatchers(
|
||||
"/style.css", "/js/**",
|
||||
"/webjars/**", "/assets/**");
|
||||
}
|
||||
}
|
@ -16,4 +16,6 @@ spring:
|
||||
suffix: .html
|
||||
enabled: true
|
||||
application:
|
||||
name: kionlion
|
||||
name: kionlion
|
||||
jwt:
|
||||
secret: cuteAndFunnyUUUUUOOOOOOOOOOOOHHHHHH
|
@ -9,6 +9,7 @@
|
||||
<body>
|
||||
<div layout:fragment="content">
|
||||
<h1>ФИЛЬМЫ</h1>
|
||||
<br/>
|
||||
<div class="container">
|
||||
<div class="row row-cols-md-2">
|
||||
<!--Карточки с фильмами-->
|
||||
|
@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru"
|
||||
xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:sec="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<title layout:title-pattern="$LAYOUT_TITLE - $CONTENT_TITLE"></title>
|
||||
@ -9,7 +9,7 @@
|
||||
<link rel="stylesheet" type="text/css" th:href="@{/style.css}">
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<header class="mb-5">
|
||||
<nav class="navbar nav-header">
|
||||
<div class="container-fluid d-flex gap-3 align-items-center header-size">
|
||||
<div>
|
||||
@ -20,7 +20,7 @@
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="menu dropdown py-3">
|
||||
<div class="menu dropdown py-3 flex-grow-1">
|
||||
<a class="btn clickable-element" role="button" id="dropdownMenuLink" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<img th:src="@{/assets/header/menu-button.png}">
|
||||
</a>
|
||||
@ -41,9 +41,9 @@
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<div layout:fragment="content"></div>
|
||||
<main layout:fragment="content" class="d-flex justify-content-center"></main>
|
||||
|
||||
<footer class="d-flex flex-wrap justify-content-between mt-auto">
|
||||
<footer class="d-flex flex-wrap justify-content-between mt-5">
|
||||
<nav class="footer-text">
|
||||
<a href="/about">О сайте</a>
|
||||
<a href="/our-partners">Наши партнеры</a>
|
||||
|
33
src/main/resources/templates/login.html
Normal file
33
src/main/resources/templates/login.html
Normal file
@ -0,0 +1,33 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
layout:decorate="~{layout}">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>LOGIN</title>
|
||||
</head>
|
||||
<body>
|
||||
<div layout:fragment="content">
|
||||
<form th:action="@{/login}" method="post">
|
||||
<div th:if="${param.error}" class="alert alert-error">
|
||||
Неверный логин или пароль
|
||||
</div>
|
||||
<div th:if="${param.logout}" class="alert alert-success">
|
||||
Вы вышли
|
||||
</div>
|
||||
<!-- Username input -->
|
||||
<div data-mdb-input-init class="form-outline mb-4">
|
||||
<input type="text" id="username-input" class="form-control" name="username" required autofocus />
|
||||
<label class="form-label" for="username-input">Username</label>
|
||||
</div>
|
||||
|
||||
<!-- Password input -->
|
||||
<div data-mdb-input-init class="form-outline mb-4">
|
||||
<input type="password" id="password-input" class="form-control" name="password" required autofocus />
|
||||
<label class="form-label" for="password-input">Password</label>
|
||||
</div>
|
||||
<!-- Submit button -->
|
||||
<button type="submit" data-mdb-button-init data-mdb-ripple-init class="btn btn-primary btn-block mb-4">Sign in</button>
|
||||
</form>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user