first commit
This commit is contained in:
@@ -0,0 +1,206 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.1.5.RELEASE</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>net.alawn</groupId>
|
||||
<artifactId>bill</artifactId>
|
||||
<packaging>war</packaging>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<name>bill</name>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
<h2.version>1.4.197</h2.version>
|
||||
<mysql.version>5.1.46</mysql.version>
|
||||
<druid.version>1.1.16</druid.version>
|
||||
<swagger2.version>2.8.0</swagger2.version>
|
||||
<mybatis-spring-boot-starter.version>2.0.0</mybatis-spring-boot-starter.version>
|
||||
<lombok.version>1.18.8</lombok.version>
|
||||
<springboot.version>2.1.5.RELEASE</springboot.version>
|
||||
<commons-lang3.version>3.7</commons-lang3.version>
|
||||
<fastjson.version>1.2.54</fastjson.version>
|
||||
<commons-io.version>2.6</commons-io.version>
|
||||
<junit.version>4.12</junit.version>
|
||||
<jjwt.version>0.10.5</jjwt.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>io.jsonwebtoken</groupId>-->
|
||||
<!-- <artifactId>jjwt</artifactId>-->
|
||||
<!-- <version>0.9.1</version>-->
|
||||
<!-- </dependency>-->
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-api</artifactId>
|
||||
<version>${jjwt.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-impl</artifactId>
|
||||
<version>${jjwt.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-jackson</artifactId>
|
||||
<scope>runtime</scope>
|
||||
<version>${jjwt.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>${junit.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>${commons-lang3.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>${fastjson.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>${commons-io.version}</version>
|
||||
</dependency>
|
||||
<!-- <dependency> -->
|
||||
<!-- <groupId>com.h2database</groupId> -->
|
||||
<!-- <artifactId>h2</artifactId> -->
|
||||
<!-- <version>${h2.version}</version> -->
|
||||
<!-- </dependency> -->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>org.hibernate</groupId>-->
|
||||
<!-- <artifactId>hibernate-ehcache</artifactId>-->
|
||||
<!-- <version>${hibernate.version}</version>-->
|
||||
<!-- </dependency>-->
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>${mysql.version}</version>
|
||||
</dependency>
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>org.hibernate</groupId>-->
|
||||
<!-- <artifactId>hibernate-entitymanager</artifactId>-->
|
||||
<!-- <version>${hibernate-entitymanager.version}</version>-->
|
||||
<!-- </dependency>-->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>com.alibaba</groupId>-->
|
||||
<!-- <artifactId>druid</artifactId>-->
|
||||
<!-- <version>${druid.version}</version>-->
|
||||
<!-- </dependency>-->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>druid-spring-boot-starter</artifactId>
|
||||
<version>${druid.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger2</artifactId>
|
||||
<version>${swagger2.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger-ui</artifactId>
|
||||
<version>${swagger2.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-batch</artifactId>
|
||||
<version>${springboot.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
<version>${springboot.version}</version>
|
||||
</dependency>
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>org.hibernate.javax.persistence</groupId>-->
|
||||
<!-- <artifactId>hibernate-jpa-2.1-api</artifactId>-->
|
||||
<!-- <version>${hibernate-jpa-api.version}</version>-->
|
||||
<!-- </dependency>-->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>org.springframework.data</groupId>-->
|
||||
<!-- <artifactId>spring-data-jpa</artifactId>-->
|
||||
<!-- <version>${spring-data-jpa.version}</version>-->
|
||||
<!-- </dependency>-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-jdbc</artifactId>
|
||||
<version>${springboot.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-quartz</artifactId>
|
||||
<version>${springboot.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
<version>${springboot.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
<version>${springboot.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<version>${springboot.version}</version>
|
||||
<!-- <exclusions>-->
|
||||
<!-- <exclusion>-->
|
||||
<!-- <groupId>org.springframework.boot</groupId>-->
|
||||
<!-- <artifactId>spring-boot-starter-tomcat</artifactId>-->
|
||||
<!-- </exclusion>-->
|
||||
<!-- </exclusions>-->
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mybatis.spring.boot</groupId>
|
||||
<artifactId>mybatis-spring-boot-starter</artifactId>
|
||||
<version>${mybatis-spring-boot-starter.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>${lombok.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<version>${springboot.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-autoconfigure</artifactId>
|
||||
<version>${springboot.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>${project.basedir}/src/main/resources</directory>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.5</version>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
<includes>
|
||||
<include>${project.basedir}/src/test/java</include>
|
||||
</includes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,19 @@
|
||||
package net.alawn.bill;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.web.servlet.ServletComponentScan;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
|
||||
|
||||
/**
|
||||
* @author Alawn
|
||||
*/
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableJpaAuditing
|
||||
@ServletComponentScan(basePackages = {"net.alawn.bill.config"})
|
||||
public class Application {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package net.alawn.bill.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import springfox.documentation.builders.ApiInfoBuilder;
|
||||
import springfox.documentation.builders.PathSelectors;
|
||||
import springfox.documentation.builders.RequestHandlerSelectors;
|
||||
import springfox.documentation.service.*;
|
||||
import springfox.documentation.spi.DocumentationType;
|
||||
import springfox.documentation.spi.service.contexts.SecurityContext;
|
||||
import springfox.documentation.spring.web.plugins.Docket;
|
||||
import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
||||
import java.util.List;
|
||||
import static com.google.common.collect.Lists.newArrayList;
|
||||
|
||||
/**
|
||||
* @author Alawn
|
||||
*/
|
||||
@Configuration
|
||||
@EnableSwagger2
|
||||
public class SwaggerConfig {
|
||||
@Bean
|
||||
public Docket createRestApi() {
|
||||
return new Docket(DocumentationType.SWAGGER_2)
|
||||
.apiInfo(apiInfo())
|
||||
.select()
|
||||
.apis(RequestHandlerSelectors.basePackage("net.alawn.bill.controller"))
|
||||
.paths(PathSelectors.any())
|
||||
.paths(PathSelectors.regex("^(?!auth).*$"))
|
||||
.build()
|
||||
.securitySchemes(securitySchemes())
|
||||
.securityContexts(securityContexts());
|
||||
}
|
||||
|
||||
private ApiInfo apiInfo() {
|
||||
return new ApiInfoBuilder()
|
||||
.title("Book API")
|
||||
.description("Bill接口")
|
||||
.termsOfServiceUrl("http://fairy8.cn")
|
||||
.contact(new Contact("Alawn","fairy8.cn","alawn.cn@gmail.com"))
|
||||
.version("1.0")
|
||||
.build();
|
||||
}
|
||||
|
||||
private List<ApiKey> securitySchemes() {
|
||||
return newArrayList(
|
||||
new ApiKey("Authorization", "Authorization", "header"));
|
||||
}
|
||||
|
||||
|
||||
private List<SecurityContext> securityContexts() {
|
||||
return newArrayList(
|
||||
SecurityContext.builder()
|
||||
.securityReferences(defaultAuth())
|
||||
.forPaths(PathSelectors.regex("^(?!auth).*$"))
|
||||
.build()
|
||||
);
|
||||
}
|
||||
List<SecurityReference> defaultAuth() {
|
||||
AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
|
||||
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
|
||||
authorizationScopes[0] = authorizationScope;
|
||||
return newArrayList(
|
||||
new SecurityReference("Authorization", authorizationScopes));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package net.alawn.bill.config;
|
||||
|
||||
import net.alawn.bill.security.AuthUser;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.domain.AuditorAware;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
* @Date: Create in 17:34 2019-05-23
|
||||
*/
|
||||
|
||||
@Configuration
|
||||
public class UserIDAuditorBean implements AuditorAware<String> {
|
||||
|
||||
@Override
|
||||
public Optional<String> getCurrentAuditor() {
|
||||
SecurityContext ctx = SecurityContextHolder.getContext();
|
||||
if (ctx == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
if (ctx.getAuthentication() == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
if (ctx.getAuthentication().getPrincipal() == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
Object principal = ctx.getAuthentication().getPrincipal();
|
||||
if (principal.getClass().isAssignableFrom(AuthUser.class)) {
|
||||
return Optional.ofNullable(((AuthUser) principal).getUsername());
|
||||
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package net.alawn.bill.controller;
|
||||
|
||||
import net.alawn.bill.entity.dto.AddUser;
|
||||
import net.alawn.bill.security.JwtAuthenticationRequest;
|
||||
import net.alawn.bill.security.JwtAuthenticationResponse;
|
||||
import net.alawn.bill.service.AuthService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
* @Date: Create in 09:59 2019-05-23
|
||||
*/
|
||||
@RestController
|
||||
public class AuthController {
|
||||
|
||||
@Value("${jwt.header}")
|
||||
private String tokenHeader;
|
||||
|
||||
@Autowired
|
||||
private AuthService authService;
|
||||
|
||||
@RequestMapping(value = "/auth", method = RequestMethod.POST)
|
||||
public ResponseEntity<?> createAuthenticationToken(
|
||||
@RequestBody JwtAuthenticationRequest authenticationRequest) throws AuthenticationException {
|
||||
final String token = authService.login(authenticationRequest.getUsername(), authenticationRequest.getPassword());
|
||||
|
||||
// Return the token
|
||||
return ResponseEntity.ok(new JwtAuthenticationResponse(token));
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/auth/refresh", method = RequestMethod.GET)
|
||||
public ResponseEntity<?> refreshAndGetAuthenticationToken(
|
||||
HttpServletRequest request) throws AuthenticationException{
|
||||
String token = request.getHeader(tokenHeader);
|
||||
String refreshedToken = authService.refresh(token);
|
||||
if(refreshedToken == null) {
|
||||
return ResponseEntity.badRequest().body(null);
|
||||
} else {
|
||||
return ResponseEntity.ok(new JwtAuthenticationResponse(refreshedToken));
|
||||
}
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/auth/register", method = RequestMethod.POST)
|
||||
public AddUser register(@RequestBody AddUser addedUser) throws AuthenticationException, HttpRequestMethodNotSupportedException {
|
||||
return authService.register(addedUser);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
package net.alawn.bill.controller;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.alawn.bill.entity.dto.AddMerchant;
|
||||
import net.alawn.bill.entity.dto.AddPost;
|
||||
import net.alawn.bill.entity.dto.AddTitle;
|
||||
import net.alawn.bill.entity.po.*;
|
||||
import net.alawn.bill.repository.*;
|
||||
import net.alawn.bill.security.AuthUser;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.security.Principal;
|
||||
import java.util.Optional;
|
||||
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
* @Date: Create in 09:59 2019-05-23
|
||||
*/
|
||||
|
||||
@Slf4j
|
||||
@RequestMapping(value = "/basic")
|
||||
@RestController
|
||||
public class BasicController {
|
||||
|
||||
@Autowired
|
||||
BookRepo bookRepo;
|
||||
|
||||
@Autowired
|
||||
ItemRepo itemRepo;
|
||||
|
||||
@Autowired
|
||||
UserRepo userRepo;
|
||||
|
||||
@Autowired
|
||||
PostRepo postRepo;
|
||||
|
||||
@Autowired
|
||||
MerchantRepo merchantRepo;
|
||||
|
||||
@Autowired
|
||||
TitleRepo titleRepo;
|
||||
|
||||
@RequestMapping(value = "/post",method = RequestMethod.POST)
|
||||
@ResponseBody
|
||||
public ResponseEntity<Post> addPost(@RequestBody AddPost addPost, Principal principal) throws URISyntaxException {
|
||||
AuthUser authUser = (AuthUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
long userId = authUser.getId();
|
||||
|
||||
/** 登记 Post */
|
||||
Post post = addPost.build();
|
||||
post.setUserId(userId);
|
||||
postRepo.save(post);
|
||||
postRepo.flush();
|
||||
return ResponseEntity.ok(post);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/post/{id}",method = RequestMethod.GET)
|
||||
@ResponseBody
|
||||
public ResponseEntity<Post> getPost(@PathVariable long id){
|
||||
log.info("post id:" + id);
|
||||
|
||||
/** 登记 Post */
|
||||
Optional<Post> post = postRepo.findById(id);
|
||||
|
||||
if(post.isPresent()) {
|
||||
return ResponseEntity.ok(post.get());
|
||||
}
|
||||
else{
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@RequestMapping(value = "/merchant",method = RequestMethod.POST)
|
||||
@ResponseBody
|
||||
public ResponseEntity<Merchant> addMerchant(@RequestBody AddMerchant addMerchant) throws URISyntaxException {
|
||||
/** 登记 Post */
|
||||
Merchant merchant = merchantRepo.save(addMerchant.build());
|
||||
merchantRepo.flush();
|
||||
return ResponseEntity.ok(merchant);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/merchant/{id}",method = RequestMethod.GET)
|
||||
@ResponseBody
|
||||
public ResponseEntity<Merchant> getMerchant(@PathVariable long id){
|
||||
/** 登记 Post */
|
||||
Optional<Merchant> merchant = merchantRepo.findById(id);
|
||||
if(merchant.isPresent()){
|
||||
return ResponseEntity.ok(merchant.get());
|
||||
}
|
||||
else{
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@RequestMapping(value = "/title",method = RequestMethod.POST)
|
||||
@ResponseBody
|
||||
public ResponseEntity<Title> addTitle(@RequestBody AddTitle addTitle) throws URISyntaxException {
|
||||
/** 登记 Post */
|
||||
Title title = titleRepo.save(addTitle.build());
|
||||
titleRepo.flush();
|
||||
return ResponseEntity.ok(title);
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/title/{id}",method = RequestMethod.GET)
|
||||
@ResponseBody
|
||||
public ResponseEntity<Title> getTitle(@PathVariable long id){
|
||||
/** 登记 Post */
|
||||
Optional<Title> title = titleRepo.findById(id);
|
||||
if(title.isPresent()) {
|
||||
return ResponseEntity.ok(title.get());
|
||||
}
|
||||
else{
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package net.alawn.bill.controller;
|
||||
|
||||
import net.alawn.bill.entity.dto.AddBill;
|
||||
import net.alawn.bill.entity.po.Book;
|
||||
import net.alawn.bill.entity.po.Item;
|
||||
import net.alawn.bill.enums.State;
|
||||
import net.alawn.bill.repository.BookRepo;
|
||||
import net.alawn.bill.repository.ItemRepo;
|
||||
import net.alawn.bill.repository.UserRepo;
|
||||
import net.alawn.bill.security.AuthUser;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
* @Date: Create in 09:59 2019-05-23
|
||||
*/
|
||||
|
||||
|
||||
@RequestMapping(value = "/bills")
|
||||
@RestController
|
||||
public class BillController {
|
||||
|
||||
@Autowired
|
||||
BookRepo bookRepo;
|
||||
|
||||
@Autowired
|
||||
ItemRepo itemRepo;
|
||||
|
||||
@Autowired
|
||||
UserRepo userRepo;
|
||||
|
||||
@RequestMapping(value = "/",method = RequestMethod.POST)
|
||||
public ResponseEntity<Book> addBook(@RequestBody AddBill addBill, Principal principal){
|
||||
AuthUser authUser = (AuthUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
long userId = authUser.getId();
|
||||
|
||||
/** 登记 book */
|
||||
Book book = bookRepo.save(new Book(userId, addBill.getPostId(), State.APPLIED,new Date(),null));
|
||||
|
||||
/** DTO -> PO 转换 */
|
||||
List<Item> items = addBill.getBillItems()
|
||||
.stream()
|
||||
.map(bill -> new Item(book.getId(),bill.getDating(),bill.getTitleId(),bill.getMerchantId(),bill.getAmount()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
/** 登记 item */
|
||||
itemRepo.saveAll(items);
|
||||
bookRepo.flush();
|
||||
itemRepo.flush();
|
||||
return ResponseEntity.ok(book);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package net.alawn.bill.entity.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
* @Date: Create in 10:47 2019-05-23
|
||||
*/
|
||||
|
||||
@Data
|
||||
public class AddBill {
|
||||
private long postId;
|
||||
List<BillItem> billItems;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package net.alawn.bill.entity.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import net.alawn.bill.entity.po.Merchant;
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
* @Date: Create in 15:21 2019-05-23
|
||||
*/
|
||||
@Data
|
||||
public class AddMerchant {
|
||||
private String abbr;
|
||||
private String name;
|
||||
|
||||
public Merchant build() {
|
||||
return Merchant.builder().abbr(abbr).name(name).build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package net.alawn.bill.entity.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import net.alawn.bill.entity.po.Post;
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
* @Date: Create in 15:20 2019-05-23
|
||||
*/
|
||||
|
||||
@Data
|
||||
public class AddPost {
|
||||
private String address ;
|
||||
private String contact ;
|
||||
private String mobile ;
|
||||
|
||||
public Post build() {
|
||||
return Post.builder().address(address).contact(contact).mobile(mobile).build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package net.alawn.bill.entity.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import net.alawn.bill.entity.po.Title;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
* @Date: Create in 10:47 2019-05-23
|
||||
*/
|
||||
|
||||
@Data
|
||||
public class AddTitle {
|
||||
private String name;
|
||||
private String abbr;
|
||||
private String taxNo;
|
||||
|
||||
public Title build() {
|
||||
return Title.builder().abbr(abbr).taxNo(taxNo).name(name).build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package net.alawn.bill.entity.dto;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Value;
|
||||
import net.alawn.bill.entity.po.User;
|
||||
|
||||
@Value
|
||||
@Builder
|
||||
public class AddUser {
|
||||
|
||||
private String username;
|
||||
private String password;
|
||||
|
||||
public User build() {
|
||||
return User.builder()
|
||||
.username(username)
|
||||
.password(password)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package net.alawn.bill.entity.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
* @Date: Create in 11:07 2019-05-23
|
||||
*/
|
||||
|
||||
@Data
|
||||
public class BillItem {
|
||||
private Date dating;
|
||||
private long titleId;
|
||||
private long merchantId;
|
||||
private BigDecimal amount;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package net.alawn.bill.entity.po;
|
||||
|
||||
import lombok.*;
|
||||
import org.hibernate.annotations.NotFound;
|
||||
import org.hibernate.annotations.NotFoundAction;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@Entity
|
||||
@Table(name = "t_bill_authorities")
|
||||
@ToString(exclude = {"user"})
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class Authority{
|
||||
|
||||
@EmbeddedId
|
||||
private AuthorityId id;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@NotFound(action = NotFoundAction.IGNORE)
|
||||
// @JoinColumn(name = "userId", referencedColumnName = "id")
|
||||
@JoinColumn(name = "userId", referencedColumnName = "id")
|
||||
// @MapsId("username")
|
||||
@MapsId("id")
|
||||
private User user;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return this == o || o instanceof Authority
|
||||
&& id != null
|
||||
&& id.equals(((Authority) o).id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 31;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package net.alawn.bill.entity.po;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.persistence.Embeddable;
|
||||
import java.io.Serializable;
|
||||
|
||||
@Builder
|
||||
@Data
|
||||
@Embeddable
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class AuthorityId implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -8173857210615808268L;
|
||||
|
||||
private Long userId;
|
||||
private String authority;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return this == o || o instanceof AuthorityId
|
||||
&& userId != null && authority != null
|
||||
&& userId == ((AuthorityId) o).userId
|
||||
&& authority.equals(((AuthorityId) o).authority);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 31;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package net.alawn.bill.entity.po;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
import net.alawn.bill.security.AuthUser;
|
||||
import org.springframework.data.annotation.*;
|
||||
import org.springframework.data.annotation.Version;
|
||||
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.persistence.Id;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author Alawn
|
||||
*/
|
||||
|
||||
@Data
|
||||
@MappedSuperclass
|
||||
@Accessors(chain = true)
|
||||
@EntityListeners(AuditingEntityListener.class)
|
||||
public class Base implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private long id;
|
||||
|
||||
// @Temporal(TemporalType.TIMESTAMP)
|
||||
// @CreationTimestamp
|
||||
@JsonIgnore
|
||||
@CreatedDate
|
||||
@Column(name="create_time")
|
||||
protected Date createTime;
|
||||
|
||||
|
||||
@JsonIgnore
|
||||
@Column(name="create_user")
|
||||
@CreatedBy
|
||||
protected String createUser;
|
||||
|
||||
// @Temporal(TemporalType.TIMESTAMP)
|
||||
// @UpdateTimestamp
|
||||
@JsonIgnore
|
||||
@LastModifiedDate
|
||||
@Column(name = "update_time")
|
||||
protected Date updateTime;
|
||||
|
||||
@JsonIgnore
|
||||
@Column(name = "update_user")
|
||||
@LastModifiedBy
|
||||
protected String updateUser;
|
||||
|
||||
@JsonIgnore
|
||||
@Version
|
||||
@Column(name = "version")
|
||||
protected Long version;
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package net.alawn.bill.entity.po;
|
||||
|
||||
import lombok.*;
|
||||
import net.alawn.bill.enums.State;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.Table;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
* @Date: Create in 10:06 2019-05-23
|
||||
*/
|
||||
|
||||
@Entity
|
||||
@Table(name="t_bill_books")
|
||||
@Data
|
||||
@ToString(callSuper = true)
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class Book extends Base{
|
||||
|
||||
private long userId;
|
||||
private long postId;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
private State state;
|
||||
|
||||
private Date applyDate;
|
||||
private Date acceptDate;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package net.alawn.bill.entity.po;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Table;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
* @Date: Create in 10:53 2019-05-23
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "t_bill_items")
|
||||
@Data
|
||||
@ToString(callSuper = true)
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class Item extends Base{
|
||||
private long bookId;
|
||||
private Date dating;
|
||||
private long titleId;
|
||||
private long merchantId;
|
||||
private BigDecimal amount;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package net.alawn.bill.entity.po;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Table;
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
* @Date: Create in 10:59 2019-05-23
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "t_bill_merchants")
|
||||
@Data
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class Merchant extends Base{
|
||||
private String abbr;
|
||||
private String name;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package net.alawn.bill.entity.po;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Table;
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
* @Date: Create in 10:17 2019-05-23
|
||||
*/
|
||||
|
||||
@Entity
|
||||
@Table(name = "t_bill_posts")
|
||||
@Data
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class Post extends Base{
|
||||
private long userId ;
|
||||
private String address ;
|
||||
private String contact ;
|
||||
private String mobile ;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package net.alawn.bill.entity.po;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
* @Date: Create in 10:17 2019-05-23
|
||||
*/
|
||||
|
||||
@Entity
|
||||
@Table(name = "t_bill_titles")
|
||||
@Data
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class Title extends Base{
|
||||
|
||||
private String name;
|
||||
private String abbr;
|
||||
@Column(length = 18)
|
||||
private String taxNo;
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package net.alawn.bill.entity.po;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import lombok.*;
|
||||
import lombok.experimental.Accessors;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author Alawn
|
||||
*/
|
||||
|
||||
@SuppressWarnings("ALL")
|
||||
@Entity
|
||||
@Builder
|
||||
@Table(
|
||||
name = "t_bill_users",
|
||||
indexes = {
|
||||
@Index(name = "t_bill_users_idx1",columnList = "create_time",unique = false),
|
||||
@Index(name = "t_bill_users_idx2",columnList = "username",unique = true)})
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@ToString(exclude = {"authorities"})
|
||||
@Slf4j
|
||||
public class User extends Base {
|
||||
|
||||
/** 用户名称 */
|
||||
private String username;
|
||||
|
||||
/** 密钥 */
|
||||
@JsonIgnore
|
||||
private String password;
|
||||
|
||||
/** 密钥 */
|
||||
private String secret;
|
||||
|
||||
/** 密码盐 */
|
||||
private String salt;
|
||||
|
||||
/** token因子 */
|
||||
private String tokenFactor;
|
||||
|
||||
/** 邮箱 */
|
||||
private String email;
|
||||
|
||||
/** 上一次重置密码时间 */
|
||||
private Date lastPasswordResetDate;
|
||||
|
||||
@OneToMany(mappedBy = "user", fetch = FetchType.EAGER)
|
||||
private Set<Authority> authorities;
|
||||
|
||||
@Builder.Default
|
||||
private boolean enabled = true;
|
||||
|
||||
// public UserDetails toUserDetails() {
|
||||
// log.info("toUserDetails.authorities:" + authorities);
|
||||
// log.info("toUserDetails.authorities:" + mapToGrantedAuthorities(authorities));
|
||||
// return new AuthUser(id,username, password, email,enabled, mapToGrantedAuthorities(authorities),lastPasswordResetDate);
|
||||
// }
|
||||
//
|
||||
//// private static Set<GrantedAuthority> mapToGrantedAuthorities(Set<Authority> authorities) {
|
||||
//// return authorities.stream()
|
||||
//// .map(authority -> new SimpleGrantedAuthority(authority.getId().getAuthority()))
|
||||
//// .collect(Collectors.toSet());
|
||||
//// }
|
||||
|
||||
// private static Set<GrantedAuthority> mapToGrantedAuthorities(Set<Authority> authorities) {
|
||||
// log.info("authorities:" + authorities);
|
||||
// log.info("authorities.stream().toString():" + authorities.stream().toString());
|
||||
// return authorities.stream()
|
||||
// .map(authority -> new SimpleGrantedAuthority(authority.getId().getAuthority()))
|
||||
// .collect(Collectors.toSet());
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package net.alawn.bill.enums;
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
* @Date: Create in 15:01 2019-03-23
|
||||
*/
|
||||
|
||||
public enum AccessProtocol {
|
||||
|
||||
/**
|
||||
* 本地直接访问
|
||||
*/
|
||||
DIRECT("本地直接访问"),
|
||||
|
||||
/**
|
||||
* Net File System
|
||||
*/
|
||||
NFS("Net File System"),
|
||||
/**
|
||||
* Server Message Block
|
||||
*/
|
||||
SMB("Server Message Block"),
|
||||
/**
|
||||
* File Transfer Protocol
|
||||
*/
|
||||
FTP("File Transfer Protocol"),
|
||||
|
||||
/**
|
||||
* Apple Filing Protocol
|
||||
*/
|
||||
AFP("Apple Filing Protocol"),
|
||||
|
||||
/**
|
||||
* Based on Secure Shell Communication Protocol
|
||||
*/
|
||||
SCP("Secure Copy"),
|
||||
/**
|
||||
* Web Distributed Authoring and Version
|
||||
*/
|
||||
WebDAV("Web Distributed Authoring and Version");
|
||||
|
||||
|
||||
private String value;
|
||||
|
||||
AccessProtocol(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package net.alawn.bill.enums;
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
* @Date: Create in 15:01 2019-03-23
|
||||
*/
|
||||
|
||||
public enum State {
|
||||
|
||||
APPLIED ( "已申请"),
|
||||
ACCEPTED ( "已受理"),
|
||||
POSTED ( "已快递");
|
||||
|
||||
private String desc;
|
||||
|
||||
State(String desc) {
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public String desc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public void setDesc(String desc) {
|
||||
this.desc = desc;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package net.alawn.bill.exception;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
* @Date: Create in 12:47 2019-03-29
|
||||
*/
|
||||
|
||||
@Slf4j
|
||||
@Data
|
||||
public class CommonException extends RuntimeException{
|
||||
protected String code;
|
||||
protected String message;
|
||||
|
||||
public CommonException(String code, String message) {
|
||||
super(message);
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public CommonException(String code, String format, Object... arguments) {
|
||||
super(String.format(format,arguments));
|
||||
this.code = code;
|
||||
this.message = String.format(format,arguments);
|
||||
}
|
||||
|
||||
public CommonException(RespMsg msg) {
|
||||
super(msg.message());
|
||||
this.message = msg.message();
|
||||
this.code = msg.code();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package net.alawn.bill.exception;
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
* @Date: Create in 17:55 2019-04-12
|
||||
*/
|
||||
public enum RespMsg {
|
||||
|
||||
NO_STORAGE_FOUND ( "200003", RespMsgConstants.NO_STORAGE_FOUND ) ,
|
||||
BLOB_DUPLICATE ( "200004", RespMsgConstants.BLOB_DUPLICATE ) ,
|
||||
BLOB_NOT_EXIST ( "200005", RespMsgConstants.BLOB_NOT_EXIST ) ,
|
||||
NO_BLOB_FOUND ( "200006", RespMsgConstants.NO_BLOB_FOUND ) ,
|
||||
BUCKET_DUPLICATE ( "200007", RespMsgConstants.BUCKET_DUPLICATE ) ,
|
||||
FILE_HANDLING ( "200008", RespMsgConstants.FILE_HANDLING ) ,
|
||||
FILE_NOT_EXIST ( "200009", RespMsgConstants.FILE_NOT_EXIST ) ,
|
||||
FILE_OCCUPIED ( "200010", RespMsgConstants.FILE_OCCUPIED ) ,
|
||||
NO_ACCESS_PERMISSION ( "200011", RespMsgConstants.NO_ACCESS_PERMISSION ) ,
|
||||
NO_BUCKET_FOUND ( "200012", RespMsgConstants.NO_BUCKET_FOUND ) ,
|
||||
NO_DEFAULT_BUCKET ( "200013", RespMsgConstants.NO_DEFAULT_BUCKET ) ,
|
||||
NO_DEFAULT_STORAGE ( "200014", RespMsgConstants.NO_DEFAULT_STORAGE ) ,
|
||||
REQUEST_PARAMS ( "200015", RespMsgConstants.REQUEST_PARAMS ) ,
|
||||
INTERNAL_ERROR ( "200016", RespMsgConstants.INTERNAL_ERROR ) ,
|
||||
NO_DATA ( "200017", RespMsgConstants.NO_DATA ) ,
|
||||
USER_ALREADY_EXIST ( "200018", RespMsgConstants.USER_ALREADY_EXIST ) ,
|
||||
USER_NOT_EXIST_OR_PASSWORD_INCORRECT ( "200019", RespMsgConstants.USER_NOT_EXIST_OR_PASSWORD_INCORRECT ) ,
|
||||
SUCCESS ( "000000", RespMsgConstants.SUCCESS ) ;
|
||||
|
||||
|
||||
private String code;
|
||||
private String message;
|
||||
|
||||
RespMsg(String code, String message) {
|
||||
this.code = code ;
|
||||
this.message = message ;
|
||||
}
|
||||
|
||||
public String code()
|
||||
{
|
||||
return code;
|
||||
}
|
||||
|
||||
public String message() { return message; }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package net.alawn.bill.exception;
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
* @Date: Create in 13:21 2019-03-29
|
||||
*/
|
||||
public final class RespMsgConstants {
|
||||
|
||||
public final static String NO_STORAGE_FOUND = "没有发现存储" ;
|
||||
public final static String BLOB_DUPLICATE = "发现重复Blob" ;
|
||||
public final static String BLOB_NOT_EXIST = "Blob对象不存在" ;
|
||||
public final static String NO_BLOB_FOUND = "Blob对象不存在" ;
|
||||
public final static String BUCKET_DUPLICATE = "发现重复Bucket" ;
|
||||
public final static String FILE_HANDLING = "文件处理异常" ;
|
||||
public final static String FILE_NOT_EXIST = "文件不存在" ;
|
||||
public final static String FILE_OCCUPIED = "文件/文件夹已被占用" ;
|
||||
public final static String NO_ACCESS_PERMISSION = "没有该访问权限" ;
|
||||
public final static String NO_BUCKET_FOUND = "没有找到Bucket" ;
|
||||
public final static String NO_DEFAULT_BUCKET = "没有找到默认Bucket" ;
|
||||
public final static String NO_DEFAULT_STORAGE = "没有找到默认存储设备" ;
|
||||
public final static String REQUEST_PARAMS = "请求参数有误" ;
|
||||
public final static String INTERNAL_ERROR = "内部错误" ;
|
||||
public final static String NO_DATA = "没有数据" ;
|
||||
public final static String USER_ALREADY_EXIST = "用户已存在" ;
|
||||
public final static String USER_NOT_EXIST_OR_PASSWORD_INCORRECT = "用户不存在或密码不正确" ;
|
||||
public final static String SUCCESS = "业务成功" ;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package net.alawn.bill.exception;
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
* @Date: Create in 15:52 2019-03-28
|
||||
*/
|
||||
|
||||
public class UserAlreadyExistException extends CommonException {
|
||||
|
||||
private final static RespMsg msg = RespMsg.USER_ALREADY_EXIST;
|
||||
|
||||
public UserAlreadyExistException() {
|
||||
super(msg.code(),msg.message());
|
||||
}
|
||||
|
||||
public UserAlreadyExistException(String message) {
|
||||
super(msg.code(),message);
|
||||
}
|
||||
|
||||
public UserAlreadyExistException(String format, Object... arguments) {
|
||||
super(msg.code(),format, arguments);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package net.alawn.bill.repository;
|
||||
|
||||
import net.alawn.bill.entity.po.Authority;
|
||||
import net.alawn.bill.entity.po.AuthorityId;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface AuthorityRepo extends JpaRepository<Authority, AuthorityId> {
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package net.alawn.bill.repository;
|
||||
|
||||
import net.alawn.bill.entity.po.Book;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
* @Date: Create in 11:14 2019-05-23
|
||||
*/
|
||||
|
||||
@Repository
|
||||
public interface BookRepo extends JpaRepository<Book, Long> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package net.alawn.bill.repository;
|
||||
|
||||
import net.alawn.bill.entity.po.Book;
|
||||
import net.alawn.bill.entity.po.Item;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
* @Date: Create in 11:14 2019-05-23
|
||||
*/
|
||||
|
||||
@Repository
|
||||
public interface ItemRepo extends JpaRepository<Item, Long> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package net.alawn.bill.repository;
|
||||
|
||||
import net.alawn.bill.entity.po.Item;
|
||||
import net.alawn.bill.entity.po.Merchant;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
* @Date: Create in 11:14 2019-05-23
|
||||
*/
|
||||
|
||||
@Repository
|
||||
public interface MerchantRepo extends JpaRepository<Merchant, Long> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package net.alawn.bill.repository;
|
||||
|
||||
import net.alawn.bill.entity.po.Item;
|
||||
import net.alawn.bill.entity.po.Post;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
* @Date: Create in 11:14 2019-05-23
|
||||
*/
|
||||
|
||||
@Repository
|
||||
public interface PostRepo extends JpaRepository<Post, Long> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package net.alawn.bill.repository;
|
||||
|
||||
import net.alawn.bill.entity.po.Post;
|
||||
import net.alawn.bill.entity.po.Title;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
* @Date: Create in 11:14 2019-05-23
|
||||
*/
|
||||
|
||||
@Repository
|
||||
public interface TitleRepo extends JpaRepository<Title, Long> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package net.alawn.bill.repository;
|
||||
|
||||
import net.alawn.bill.entity.po.User;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface UserRepo extends JpaRepository<User, String> {
|
||||
User findByUsername(String username);
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package net.alawn.bill.security;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import lombok.ToString;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
* @Date: Create in 16:09 2019-05-20
|
||||
*/
|
||||
@ToString(callSuper = true)
|
||||
public class AuthUser implements UserDetails {
|
||||
private final long id;
|
||||
private final String username;
|
||||
private final String password;
|
||||
private final boolean enabled;
|
||||
private final Collection<? extends GrantedAuthority> authorities;
|
||||
private final Date lastPasswordResetDate;
|
||||
|
||||
public AuthUser(long id, String username, String password, String email, boolean enabled, Collection<? extends GrantedAuthority> authorities, Date lastPasswordResetDate) {
|
||||
this.id = id;
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
this.enabled = enabled;
|
||||
this.authorities = authorities;
|
||||
this.lastPasswordResetDate = lastPasswordResetDate;
|
||||
}
|
||||
|
||||
// 返回分配给用户的角色列表
|
||||
@Override
|
||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||
return authorities;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
// 账户是否未过期
|
||||
@JsonIgnore
|
||||
@Override
|
||||
public boolean isAccountNonExpired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 账户是否未锁定
|
||||
@JsonIgnore
|
||||
@Override
|
||||
public boolean isAccountNonLocked() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 密码是否未过期
|
||||
@JsonIgnore
|
||||
@Override
|
||||
public boolean isCredentialsNonExpired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 账户是否激活
|
||||
@JsonIgnore
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
// 这个是自定义的,返回上次密码重置日期
|
||||
@JsonIgnore
|
||||
public Date getLastPasswordResetDate() {
|
||||
return lastPasswordResetDate;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package net.alawn.bill.security;
|
||||
|
||||
import net.alawn.bill.entity.po.User;
|
||||
import net.alawn.bill.repository.UserRepo;
|
||||
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.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
* @Date: Create in 16:46 2019-05-20
|
||||
*/
|
||||
@Service("authUserDetailsService")
|
||||
public class AuthUserDetailsServiceImpl implements UserDetailsService {
|
||||
|
||||
@Autowired
|
||||
private UserRepo userRepo;
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException {
|
||||
|
||||
User user = userRepo.findByUsername(name);
|
||||
|
||||
if (user == null) {
|
||||
throw new UsernameNotFoundException("UsernameNotFoundException");
|
||||
} else {
|
||||
return UserFactory.createAuthUser(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package net.alawn.bill.security;
|
||||
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
|
||||
@Component
|
||||
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint, Serializable {
|
||||
|
||||
private static final long serialVersionUID = -8970718410437077606L;
|
||||
|
||||
@Override
|
||||
public void commence(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
AuthenticationException authException) throws IOException {
|
||||
// This is invoked when user tries to access a secured REST resource without supplying any credentials
|
||||
// We should just send a 401 Unauthorized response because there is no 'login page' to redirect to
|
||||
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package net.alawn.bill.security;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
* @Date: Create in 17:29 2019-05-20
|
||||
*/
|
||||
|
||||
@Data
|
||||
public class JwtAuthenticationRequest {
|
||||
private String username;
|
||||
private String password;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package net.alawn.bill.security;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
* @Date: Create in 17:30 2019-05-20
|
||||
*/
|
||||
|
||||
@Data
|
||||
public class JwtAuthenticationResponse {
|
||||
|
||||
private String token;
|
||||
|
||||
public JwtAuthenticationResponse(String token) {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package net.alawn.bill.security;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
* @Date: Create in 16:24 2019-05-20
|
||||
*/
|
||||
|
||||
|
||||
@Component
|
||||
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
|
||||
|
||||
@Qualifier("authUserDetailsService")
|
||||
@Autowired
|
||||
private UserDetailsService userDetailsService;
|
||||
|
||||
@Autowired
|
||||
private JwtTokenUtil jwtTokenUtil;
|
||||
|
||||
@Value("${jwt.header}")
|
||||
private String tokenHeader;
|
||||
|
||||
@Value("${jwt.tokenHead}")
|
||||
private String tokenHead;
|
||||
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
|
||||
// logger.info("doFilterInternal");
|
||||
// String authHeader = request.getHeader("Authorization");
|
||||
String authHeader = request.getHeader(this.tokenHeader);
|
||||
// logger.info("authHeader:" + authHeader);
|
||||
|
||||
// if (authHeader != null && authHeader.startsWith("Bearer ")) {
|
||||
if (authHeader != null && authHeader.startsWith(tokenHead)) {
|
||||
final String authToken = authHeader.substring(tokenHead.length()); // The part after "Bearer "
|
||||
logger.info("authToken:" + authToken);
|
||||
String username = jwtTokenUtil.getUsernameFromToken(authToken);
|
||||
// logger.info("username" + username);
|
||||
// logger.info("checking authentication " + username);
|
||||
|
||||
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
|
||||
|
||||
AuthUser authUser = (AuthUser) this.userDetailsService.loadUserByUsername(username);
|
||||
logger.info("userDetails:" + authUser);
|
||||
|
||||
if (jwtTokenUtil.validateToken(authToken, authUser)) {
|
||||
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(authUser, null, authUser.getAuthorities());
|
||||
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails( request));
|
||||
logger.info("authenticated user " + username + ", setting security context");
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
}
|
||||
}
|
||||
}
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
package net.alawn.bill.security;
|
||||
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.security.Keys;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
* @Date: Create in 17:50 2019-05-17
|
||||
*/
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class JwtTokenUtil {
|
||||
// private static Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256) ;
|
||||
@Value("${jwt.secret}")
|
||||
private String secret;// = "11111111111111111111111111111111";
|
||||
@Value("${jwt.expiration}")
|
||||
private long expiration;
|
||||
private static final String issuer = "bill" ;
|
||||
private static final String subject = "bill" ;
|
||||
private static final String CLAIM_KEY_USERNAME = "sub" ;
|
||||
private static final String CLAIM_KEY_CREATED = "created" ;
|
||||
|
||||
/**
|
||||
* 签发JWT
|
||||
*/
|
||||
public String generateToken(UserDetails userDetails) {
|
||||
Map<String, Object> claims = new HashMap<>();
|
||||
claims.put(CLAIM_KEY_USERNAME, userDetails.getUsername());
|
||||
claims.put(CLAIM_KEY_CREATED, new Date());
|
||||
return generateToken(claims);
|
||||
}
|
||||
|
||||
String generateToken(Map<String, Object> claims) {
|
||||
log.info("secret:" + secret);
|
||||
// Key key = Keys.hmacShaKeyFor(secret.getBytes());
|
||||
return Jwts.builder()
|
||||
.setSubject(subject)
|
||||
.setIssuer(issuer)
|
||||
.setClaims(claims)
|
||||
.setIssuedAt(new Date())
|
||||
.setExpiration(generateExpirationDate())
|
||||
.signWith(generalKey())
|
||||
.compact();
|
||||
}
|
||||
|
||||
|
||||
public boolean canTokenBeRefreshed(String token,Date lastPasswordReset) {
|
||||
final Date created = getCreatedDateFromToken(token);
|
||||
return !isCreatedBeforeLastPasswordReset(created, lastPasswordReset)
|
||||
&& !isTokenExpired(token);
|
||||
}
|
||||
|
||||
public String getUsernameFromToken(String token) {
|
||||
String username;
|
||||
try {
|
||||
final Claims claims = getClaimsFromToken(token);
|
||||
log.info("claims:" + claims);
|
||||
// username = claims.getSubject();
|
||||
username = (String) claims.get(CLAIM_KEY_USERNAME);
|
||||
log.info("username:" + username);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
username = null;
|
||||
}
|
||||
return username;
|
||||
}
|
||||
|
||||
public String refreshToken(String token) {
|
||||
String refreshedToken;
|
||||
try {
|
||||
final Claims claims = getClaimsFromToken(token);
|
||||
claims.put(CLAIM_KEY_CREATED, new Date());
|
||||
refreshedToken = generateToken(claims);
|
||||
} catch (Exception e) {
|
||||
refreshedToken = null;
|
||||
}
|
||||
return refreshedToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证JWT
|
||||
*/
|
||||
public boolean validateToken(String token, UserDetails userDetails)
|
||||
{
|
||||
// User user = userDetails;
|
||||
String username = getUsernameFromToken( token );
|
||||
return (username.equals( userDetails.getUsername() ) && !isTokenExpired( token ));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取token是否过期
|
||||
*/
|
||||
public Boolean isTokenExpired(String token) {
|
||||
Date expiration = getExpirationDateFromToken( token );
|
||||
return expiration.before( new Date() );
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取token的过期时间
|
||||
*/
|
||||
public Date getExpirationDateFromToken(String token) {
|
||||
Date expiration = getClaimsFromToken( token ).getExpiration();
|
||||
return expiration;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析JWT
|
||||
*/
|
||||
private Claims getClaimsFromToken(String token) {
|
||||
log.info("getClaimsFromToken");
|
||||
log.info("secret:" + secret);
|
||||
// Key key = Keys.hmacShaKeyFor(secret.getBytes());
|
||||
Claims claims = Jwts.parser()
|
||||
.setSigningKey(generalKey())
|
||||
.parseClaimsJws(token)
|
||||
.getBody();
|
||||
log.info("claims:" + claims);
|
||||
return claims;
|
||||
}
|
||||
|
||||
private Date generateExpirationDate() {
|
||||
return new Date(System.currentTimeMillis() + expiration * 1000);
|
||||
}
|
||||
|
||||
private Boolean isCreatedBeforeLastPasswordReset(Date created, Date lastPasswordReset) {
|
||||
return (lastPasswordReset != null && created.before(lastPasswordReset));
|
||||
}
|
||||
|
||||
public Date getCreatedDateFromToken(String token) {
|
||||
Date created;
|
||||
try {
|
||||
final Claims claims = getClaimsFromToken(token);
|
||||
created = new Date((Long) claims.get(CLAIM_KEY_CREATED));
|
||||
} catch (Exception e) {
|
||||
created = null;
|
||||
}
|
||||
return created;
|
||||
}
|
||||
|
||||
private SecretKey generalKey(){
|
||||
log.info("generalKey");
|
||||
log.info("secret:" + secret);
|
||||
byte[] encodedKey = null;
|
||||
// try {
|
||||
//// encodedKey = Base64.decodeBase64(secret.getBytes("UTF-8"));
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// log.info("encodedKey:" + encodedKey);
|
||||
// SecretKey key = Keys.hmacShaKeyFor(encodedKey);
|
||||
|
||||
|
||||
SecretKey key = null;
|
||||
try {
|
||||
key = Keys.hmacShaKeyFor(secret.getBytes("UTF-8"));
|
||||
}
|
||||
catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package net.alawn.bill.security;
|
||||
|
||||
import net.alawn.bill.entity.po.Authority;
|
||||
import net.alawn.bill.entity.po.User;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
* @Date: Create in 16:45 2019-05-20
|
||||
*/
|
||||
public class UserFactory {
|
||||
|
||||
private UserFactory() {
|
||||
}
|
||||
|
||||
public static AuthUser createAuthUser(User user) {
|
||||
// user.toUserDetails();
|
||||
return new AuthUser(
|
||||
user.getId(),
|
||||
user.getUsername(),
|
||||
user.getPassword(),
|
||||
user.getEmail(),
|
||||
user.isEnabled(),
|
||||
mapToGrantedAuthorities(user.getAuthorities()),
|
||||
user.getLastPasswordResetDate()
|
||||
);
|
||||
}
|
||||
|
||||
private static Set<GrantedAuthority> mapToGrantedAuthorities(Set<Authority> authorities) {
|
||||
return authorities.stream()
|
||||
.map(authority -> new SimpleGrantedAuthority(authority.getId().getAuthority()))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
// private static List<GrantedAuthority> mapToGrantedAuthorities(List<String> authorities) {
|
||||
// return authorities.stream()
|
||||
// .map(SimpleGrantedAuthority::new)
|
||||
// .collect(Collectors.toList());
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
package net.alawn.bill.security;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
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.config.BeanIds;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||
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.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.security.web.firewall.HttpFirewall;
|
||||
import org.springframework.security.web.firewall.StrictHttpFirewall;
|
||||
import org.springframework.util.DigestUtils;
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
* @Date: Create in 16:53 2019-05-17
|
||||
*/
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Qualifier("authUserDetailsService")
|
||||
@Autowired
|
||||
private UserDetailsService userDetailsService;
|
||||
|
||||
@Autowired
|
||||
private JwtAuthenticationEntryPoint unauthorizedHandler;
|
||||
|
||||
@Bean
|
||||
public JwtAuthenticationTokenFilter authenticationTokenFilterBean(){
|
||||
return new JwtAuthenticationTokenFilter();
|
||||
}
|
||||
|
||||
@Bean(name = BeanIds.AUTHENTICATION_MANAGER)
|
||||
@Override
|
||||
public AuthenticationManager authenticationManagerBean() throws Exception {
|
||||
return super.authenticationManagerBean();
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
|
||||
authenticationManagerBuilder
|
||||
// 设置UserDetailsService
|
||||
.userDetailsService(this.userDetailsService)
|
||||
// 使用BCrypt进行密码的hash
|
||||
.passwordEncoder(passwordEncoder());
|
||||
|
||||
}
|
||||
|
||||
/** 装载BCrypt密码编码器 */
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
|
||||
/** 自定义防火墙 */
|
||||
@Bean
|
||||
public HttpFirewall allowUrlEncodedSlashHttpFirewall() {
|
||||
StrictHttpFirewall firewall = new StrictHttpFirewall();
|
||||
firewall.setAllowUrlEncodedSlash(true);
|
||||
firewall.setAllowSemicolon(true);
|
||||
return firewall;
|
||||
}
|
||||
|
||||
/** Security Http 配置 */
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http.csrf().disable() // 去掉跨域
|
||||
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler)
|
||||
.and()
|
||||
.authorizeRequests()
|
||||
.antMatchers("/").permitAll()
|
||||
.antMatchers("/druid/**").permitAll()
|
||||
.antMatchers("/swagger*").permitAll()
|
||||
.antMatchers( HttpMethod.GET, "/","/*.html", "/favicon.ico", "/**/*.html", "/**/*.css", "/**/*.js").permitAll()
|
||||
.antMatchers("/auth/**").permitAll()
|
||||
.antMatchers("/bill/**").authenticated()
|
||||
.antMatchers("/basic/**/*").authenticated()
|
||||
// .antMatchers("/auth/**").permitAll().anyRequest().authenticated()
|
||||
.and()
|
||||
.formLogin().loginPage("/").permitAll()
|
||||
.and()
|
||||
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 去掉Session
|
||||
.and()
|
||||
.logout().permitAll() ;
|
||||
|
||||
// 添加JWT logger
|
||||
http.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
|
||||
|
||||
// 禁用缓存
|
||||
http.headers().cacheControl(); // 禁用缓存
|
||||
}
|
||||
|
||||
/** Security Web 配置 */
|
||||
@Override
|
||||
public void configure(WebSecurity web) throws Exception {
|
||||
super.configure(web);
|
||||
// @formatter:off
|
||||
web.httpFirewall(allowUrlEncodedSlashHttpFirewall());
|
||||
}
|
||||
|
||||
/** Security Authentication 配置 */
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
||||
// auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
|
||||
|
||||
//校验用户
|
||||
auth.userDetailsService(userDetailsService).passwordEncoder( new PasswordEncoder() {
|
||||
//对密码进行加密
|
||||
@Override
|
||||
public String encode(CharSequence charSequence) {
|
||||
System.out.println(charSequence.toString());
|
||||
return DigestUtils.md5DigestAsHex(charSequence.toString().getBytes());
|
||||
}
|
||||
//对密码进行判断匹配
|
||||
@Override
|
||||
public boolean matches(CharSequence charSequence, String s) {
|
||||
String encode = DigestUtils.md5DigestAsHex(charSequence.toString().getBytes());
|
||||
boolean res = s.equals( encode );
|
||||
return res;
|
||||
}
|
||||
} );
|
||||
}
|
||||
// @Override
|
||||
// public void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
// // 使用自定义身份验证组件
|
||||
// auth.authenticationProvider(new CustomAuthenticationProvider(userDetailsService));
|
||||
// }
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package net.alawn.bill.service;
|
||||
|
||||
import net.alawn.bill.entity.dto.AddUser;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.web.HttpRequestMethodNotSupportedException;
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
* @Date: Create in 15:58 2019-05-20
|
||||
*/
|
||||
public interface AuthService {
|
||||
AddUser register(AddUser userDTO) throws HttpRequestMethodNotSupportedException, AuthenticationException;
|
||||
String login(String username, String password);
|
||||
String refresh(String oldToken);
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
package net.alawn.bill.service.impl;
|
||||
|
||||
import net.alawn.bill.entity.dto.AddUser;
|
||||
import net.alawn.bill.entity.po.Authority;
|
||||
import net.alawn.bill.entity.po.AuthorityId;
|
||||
import net.alawn.bill.entity.po.User;
|
||||
import net.alawn.bill.exception.CommonException;
|
||||
import net.alawn.bill.exception.RespMsg;
|
||||
import net.alawn.bill.repository.AuthorityRepo;
|
||||
import net.alawn.bill.repository.UserRepo;
|
||||
import net.alawn.bill.security.AuthUser;
|
||||
import net.alawn.bill.security.JwtTokenUtil;
|
||||
import net.alawn.bill.service.AuthService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
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.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
|
||||
/**
|
||||
* @Author: Alawn
|
||||
* @Description:
|
||||
* @Date: Create in 15:59 2019-05-20
|
||||
*/
|
||||
|
||||
@Service
|
||||
//@AllArgsConstructor(onConstructor = @__(@Autowired))
|
||||
public class AuthServiceImpl implements AuthService {
|
||||
|
||||
@Autowired
|
||||
private AuthenticationManager authenticationManager;
|
||||
|
||||
@Qualifier("authUserDetailsService")
|
||||
@Autowired
|
||||
private UserDetailsService userDetailsService;
|
||||
|
||||
@Autowired
|
||||
private JwtTokenUtil jwtTokenUtil;
|
||||
|
||||
@Autowired
|
||||
private UserRepo userRepo ;
|
||||
|
||||
@Value("${jwt.tokenHead}")
|
||||
private String tokenHead;
|
||||
|
||||
@Autowired
|
||||
private AuthorityRepo authorityRepo;
|
||||
|
||||
|
||||
// @Autowired
|
||||
// public AuthServiceImpl(AuthenticationManager authenticationManager) {
|
||||
// this.authenticationManager = authenticationManager;
|
||||
// }
|
||||
|
||||
@Override
|
||||
public AddUser register(AddUser userDTO) throws AuthenticationException {
|
||||
final String username = userDTO.getUsername();
|
||||
|
||||
if(userRepo.findByUsername(username) != null) {
|
||||
throw new CommonException(RespMsg.USER_ALREADY_EXIST);
|
||||
}
|
||||
|
||||
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
|
||||
final String rawPassword = userDTO.getPassword();
|
||||
User user = User.builder()
|
||||
.username(username)
|
||||
.password(encoder.encode(rawPassword)).build();
|
||||
User saved = userRepo.save(user);
|
||||
Authority savedAuth = authorityRepo.save(
|
||||
Authority.builder()
|
||||
.user(saved)
|
||||
.id(AuthorityId.builder()
|
||||
.userId(saved.getId())
|
||||
.authority("ROLE_USER")
|
||||
.build())
|
||||
.build());
|
||||
userRepo.flush();
|
||||
authorityRepo.flush();
|
||||
return userDTO;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String login(String username, String password) {
|
||||
UsernamePasswordAuthenticationToken upToken = new UsernamePasswordAuthenticationToken(username, password);
|
||||
final Authentication authentication = authenticationManager.authenticate(upToken);
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
|
||||
final UserDetails userDetails = userDetailsService.loadUserByUsername(username);
|
||||
final String token = jwtTokenUtil.generateToken(userDetails);
|
||||
return token;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String refresh(String oldToken) {
|
||||
final String token = oldToken.substring(tokenHead.length());
|
||||
String username = jwtTokenUtil.getUsernameFromToken(token);
|
||||
AuthUser user = (AuthUser)userDetailsService.loadUserByUsername(username);
|
||||
if (jwtTokenUtil.canTokenBeRefreshed(token, user.getLastPasswordResetDate())){
|
||||
return jwtTokenUtil.refreshToken(token);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void authenticateUser(AddUser userDTO) {
|
||||
UsernamePasswordAuthenticationToken upToken = new UsernamePasswordAuthenticationToken(userDTO.getUsername(), userDTO.getPassword());
|
||||
// 进行安全认证
|
||||
final Authentication authentication = authenticationManager.authenticate(upToken);
|
||||
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
server.port= 30000
|
||||
|
||||
# JWT
|
||||
jwt.header=Authorization
|
||||
jwt.secret=8UbBmq9LNnPKFc4sFN7ZF2TTCGbCXTsy
|
||||
jwt.expiration=604800
|
||||
jwt.tokenHead=Bearer
|
||||
jwt.route.authentication.path=auth
|
||||
jwt.route.authentication.refresh=refresh
|
||||
jwt.route.authentication.register=auth/register
|
||||
|
||||
|
||||
# JPA
|
||||
spring.jpa.properties.show-sql=true
|
||||
spring.jpa.properties.hibernate.format_sql=true
|
||||
spring.jpa.properties.hibernate.use_sql_comments=true //指出是什么操作生成了该语句
|
||||
spring.jpa.show-sql=false
|
||||
spring.jpa.generate-ddl=true
|
||||
spring.jpa.properties.hibernate.hbm2ddl.auto=update
|
||||
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
|
||||
|
||||
# Security
|
||||
spring.security.user.username=admin
|
||||
spring.security.user.password=admin
|
||||
spring.security.password=admin
|
||||
|
||||
|
||||
# Durid
|
||||
spring.datasource.sql-script-encoding=utf-8
|
||||
spring.datasource.initialization-mode=always
|
||||
spring.datasource.druid.driverClassName=com.mysql.jdbc.Driver
|
||||
spring.datasource.druid.url=jdbc:mysql://fairy8.cn:3308/test?useUnicode=true&characterEncoding=utf-8&useSSL=false
|
||||
spring.datasource.druid.max-open-prepared-statements=25
|
||||
spring.datasource.druid.username=test
|
||||
spring.datasource.druid.password=newland15%
|
||||
spring.datasource.druid.initialSize=5
|
||||
spring.datasource.druid.minIdle=1
|
||||
spring.datasource.druid.maxActive=50
|
||||
spring.datasource.druid.maxWait=60000
|
||||
spring.datasource.druid.timeBetweenEvictionRunsMillis=60000
|
||||
spring.datasource.druid.minEvictableIdleTimeMillis=300000
|
||||
spring.datasource.druid.validationQuery=SELECT 1 FROM DUAL
|
||||
spring.datasource.druid.testWhileIdle=true
|
||||
spring.datasource.druid.testOnBorrow=false
|
||||
spring.datasource.druid.testOnReturn=false
|
||||
spring.datasource.druid.poolPreparedStatements=false
|
||||
spring.datasource.druid.maxPoolPreparedStatementPerConnectionSize=20
|
||||
|
||||
# Druid.Master 监控配置
|
||||
spring.datasource.druid.connection-properties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
|
||||
spring.datasource.druid.stat-view-servlet.reset-enable=false
|
||||
spring.datasource.druid.master.filter.stat.log-slow-sql=true
|
||||
spring.datasource.druid.filter.stat.slow-sql-millis=2000
|
||||
spring.datasource.druid.filters=stat,wall,slf4j
|
||||
#spring.datasource.druid.filters=config,stat,wall,slf4j
|
||||
spring.datasource.druid.filter.slf4j.connection-log-enabled=true
|
||||
spring.datasource.druid.useGlobalDataSourceStat=true
|
||||
spring.datasource.druid.filter.slf4j.enabled=true
|
||||
spring.datasource.druid.filter.slf4j.data-source-log-enabled=true
|
||||
spring.datasource.druid.filter.slf4j.result-set-log-enabled=true
|
||||
spring.datasource.druid.filter.slf4j.statement-parameter-set-log-enabled=true
|
||||
spring.datasource.druid.filter.slf4j.statement-parameter-clear-log-enable=true
|
||||
spring.datasource.druid.filter.slf4j.statement-create-after-log-enabled=true
|
||||
spring.datasource.druid.filter.slf4j.statement-log-enabled=true
|
||||
spring.datasource.druid.filter.slf4j.statement-executable-sql-log-enable=true
|
||||
spring.datasource.druid.filter.slf4j.statement-execute-after-log-enabled=true
|
||||
spring.datasource.druid.filter.slf4j.statement-execute-update-after-log-enabled=true
|
||||
spring.datasource.druid.filter.slf4j.statement-execute-batch-after-log-enabled=true
|
||||
|
||||
# Logging
|
||||
logging.level.root=info
|
||||
logging.level.org.springframework=info
|
||||
logging.level.org.springframework.jdbc=debug
|
||||
logging.level.org.springframework.boot=info
|
||||
logging.level.org.mybatis=info
|
||||
logging.level.org.hibernate.SQL=debug
|
||||
logging.level.com.alibaba.druid=debug
|
||||
logging.level.com.github.trang=info
|
||||
logging.level.executableSql=debug
|
||||
|
||||
Reference in New Issue
Block a user