From 54ecf61073bf4920dbbe8964a160a05406a8c785 Mon Sep 17 00:00:00 2001 From: zhao_lei Date: Thu, 23 May 2019 17:46:46 +0800 Subject: [PATCH] first commit --- pom.xml | 206 ++++++++++++++++++ src/main/java/net/alawn/bill/Application.java | 19 ++ .../net/alawn/bill/config/SwaggerConfig.java | 67 ++++++ .../alawn/bill/config/UserIDAuditorBean.java | 40 ++++ .../alawn/bill/controller/AuthController.java | 58 +++++ .../bill/controller/BasicController.java | 126 +++++++++++ .../alawn/bill/controller/BillController.java | 62 ++++++ .../net/alawn/bill/entity/dto/AddBill.java | 17 ++ .../alawn/bill/entity/dto/AddMerchant.java | 19 ++ .../net/alawn/bill/entity/dto/AddPost.java | 21 ++ .../net/alawn/bill/entity/dto/AddTitle.java | 23 ++ .../net/alawn/bill/entity/dto/AddUser.java | 20 ++ .../net/alawn/bill/entity/dto/BillItem.java | 20 ++ .../net/alawn/bill/entity/po/Authority.java | 41 ++++ .../net/alawn/bill/entity/po/AuthorityId.java | 35 +++ .../java/net/alawn/bill/entity/po/Base.java | 65 ++++++ .../java/net/alawn/bill/entity/po/Book.java | 35 +++ .../java/net/alawn/bill/entity/po/Item.java | 28 +++ .../net/alawn/bill/entity/po/Merchant.java | 23 ++ .../java/net/alawn/bill/entity/po/Post.java | 27 +++ .../java/net/alawn/bill/entity/po/Title.java | 26 +++ .../java/net/alawn/bill/entity/po/User.java | 84 +++++++ .../net/alawn/bill/enums/AccessProtocol.java | 57 +++++ src/main/java/net/alawn/bill/enums/State.java | 28 +++ .../alawn/bill/exception/CommonException.java | 35 +++ .../net/alawn/bill/exception/RespMsg.java | 45 ++++ .../bill/exception/RespMsgConstants.java | 28 +++ .../exception/UserAlreadyExistException.java | 24 ++ .../alawn/bill/repository/AuthorityRepo.java | 10 + .../net/alawn/bill/repository/BookRepo.java | 16 ++ .../net/alawn/bill/repository/ItemRepo.java | 17 ++ .../alawn/bill/repository/MerchantRepo.java | 17 ++ .../net/alawn/bill/repository/PostRepo.java | 17 ++ .../net/alawn/bill/repository/TitleRepo.java | 17 ++ .../net/alawn/bill/repository/UserRepo.java | 10 + .../net/alawn/bill/security/AuthUser.java | 90 ++++++++ .../security/AuthUserDetailsServiceImpl.java | 33 +++ .../security/JwtAuthenticationEntryPoint.java | 25 +++ .../security/JwtAuthenticationRequest.java | 15 ++ .../security/JwtAuthenticationResponse.java | 20 ++ .../JwtAuthenticationTokenFilter.java | 74 +++++++ .../net/alawn/bill/security/JwtTokenUtil.java | 178 +++++++++++++++ .../net/alawn/bill/security/UserFactory.java | 46 ++++ .../bill/security/WebSecurityConfig.java | 143 ++++++++++++ .../net/alawn/bill/service/AuthService.java | 16 ++ .../bill/service/impl/AuthServiceImpl.java | 120 ++++++++++ src/main/resources/application.properties | 80 +++++++ 47 files changed, 2223 insertions(+) create mode 100644 pom.xml create mode 100644 src/main/java/net/alawn/bill/Application.java create mode 100644 src/main/java/net/alawn/bill/config/SwaggerConfig.java create mode 100644 src/main/java/net/alawn/bill/config/UserIDAuditorBean.java create mode 100644 src/main/java/net/alawn/bill/controller/AuthController.java create mode 100644 src/main/java/net/alawn/bill/controller/BasicController.java create mode 100644 src/main/java/net/alawn/bill/controller/BillController.java create mode 100644 src/main/java/net/alawn/bill/entity/dto/AddBill.java create mode 100644 src/main/java/net/alawn/bill/entity/dto/AddMerchant.java create mode 100644 src/main/java/net/alawn/bill/entity/dto/AddPost.java create mode 100644 src/main/java/net/alawn/bill/entity/dto/AddTitle.java create mode 100644 src/main/java/net/alawn/bill/entity/dto/AddUser.java create mode 100644 src/main/java/net/alawn/bill/entity/dto/BillItem.java create mode 100644 src/main/java/net/alawn/bill/entity/po/Authority.java create mode 100644 src/main/java/net/alawn/bill/entity/po/AuthorityId.java create mode 100644 src/main/java/net/alawn/bill/entity/po/Base.java create mode 100644 src/main/java/net/alawn/bill/entity/po/Book.java create mode 100644 src/main/java/net/alawn/bill/entity/po/Item.java create mode 100644 src/main/java/net/alawn/bill/entity/po/Merchant.java create mode 100644 src/main/java/net/alawn/bill/entity/po/Post.java create mode 100644 src/main/java/net/alawn/bill/entity/po/Title.java create mode 100644 src/main/java/net/alawn/bill/entity/po/User.java create mode 100644 src/main/java/net/alawn/bill/enums/AccessProtocol.java create mode 100644 src/main/java/net/alawn/bill/enums/State.java create mode 100644 src/main/java/net/alawn/bill/exception/CommonException.java create mode 100644 src/main/java/net/alawn/bill/exception/RespMsg.java create mode 100644 src/main/java/net/alawn/bill/exception/RespMsgConstants.java create mode 100644 src/main/java/net/alawn/bill/exception/UserAlreadyExistException.java create mode 100644 src/main/java/net/alawn/bill/repository/AuthorityRepo.java create mode 100644 src/main/java/net/alawn/bill/repository/BookRepo.java create mode 100644 src/main/java/net/alawn/bill/repository/ItemRepo.java create mode 100644 src/main/java/net/alawn/bill/repository/MerchantRepo.java create mode 100644 src/main/java/net/alawn/bill/repository/PostRepo.java create mode 100644 src/main/java/net/alawn/bill/repository/TitleRepo.java create mode 100644 src/main/java/net/alawn/bill/repository/UserRepo.java create mode 100644 src/main/java/net/alawn/bill/security/AuthUser.java create mode 100644 src/main/java/net/alawn/bill/security/AuthUserDetailsServiceImpl.java create mode 100644 src/main/java/net/alawn/bill/security/JwtAuthenticationEntryPoint.java create mode 100644 src/main/java/net/alawn/bill/security/JwtAuthenticationRequest.java create mode 100644 src/main/java/net/alawn/bill/security/JwtAuthenticationResponse.java create mode 100644 src/main/java/net/alawn/bill/security/JwtAuthenticationTokenFilter.java create mode 100644 src/main/java/net/alawn/bill/security/JwtTokenUtil.java create mode 100644 src/main/java/net/alawn/bill/security/UserFactory.java create mode 100644 src/main/java/net/alawn/bill/security/WebSecurityConfig.java create mode 100644 src/main/java/net/alawn/bill/service/AuthService.java create mode 100644 src/main/java/net/alawn/bill/service/impl/AuthServiceImpl.java create mode 100644 src/main/resources/application.properties diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..a877edb --- /dev/null +++ b/pom.xml @@ -0,0 +1,206 @@ + + + + org.springframework.boot + spring-boot-starter-parent + 2.1.5.RELEASE + + 4.0.0 + net.alawn + bill + war + 1.0.0-SNAPSHOT + bill + + + UTF-8 + 1.8 + 1.4.197 + 5.1.46 + 1.1.16 + 2.8.0 + 2.0.0 + 1.18.8 + 2.1.5.RELEASE + 3.7 + 1.2.54 + 2.6 + 4.12 + 0.10.5 + + + + + + + + + io.jsonwebtoken + jjwt-api + ${jjwt.version} + + + io.jsonwebtoken + jjwt-impl + ${jjwt.version} + runtime + + + io.jsonwebtoken + jjwt-jackson + runtime + ${jjwt.version} + + + junit + junit + ${junit.version} + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + com.alibaba + fastjson + ${fastjson.version} + + + commons-io + commons-io + ${commons-io.version} + + + + + + + + + + + + + mysql + mysql-connector-java + ${mysql.version} + + + + + + + + + + + + + com.alibaba + druid-spring-boot-starter + ${druid.version} + + + io.springfox + springfox-swagger2 + ${swagger2.version} + + + io.springfox + springfox-swagger-ui + ${swagger2.version} + + + org.springframework.boot + spring-boot-starter-batch + ${springboot.version} + + + org.springframework.boot + spring-boot-starter-data-jpa + ${springboot.version} + + + + + + + + + + + + + org.springframework.boot + spring-boot-starter-jdbc + ${springboot.version} + + + org.springframework.boot + spring-boot-starter-quartz + ${springboot.version} + + + org.springframework.boot + spring-boot-starter-security + ${springboot.version} + + + org.springframework.boot + spring-boot-starter-validation + ${springboot.version} + + + org.springframework.boot + spring-boot-starter-web + ${springboot.version} + + + + + + + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + ${mybatis-spring-boot-starter.version} + + + org.projectlombok + lombok + ${lombok.version} + + + org.springframework.boot + spring-boot-starter-test + ${springboot.version} + + + org.springframework.boot + spring-boot-autoconfigure + ${springboot.version} + + + + + + ${project.basedir}/src/main/resources + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.5 + + true + + ${project.basedir}/src/test/java + + + + + + diff --git a/src/main/java/net/alawn/bill/Application.java b/src/main/java/net/alawn/bill/Application.java new file mode 100644 index 0000000..cb8d778 --- /dev/null +++ b/src/main/java/net/alawn/bill/Application.java @@ -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); + } +} diff --git a/src/main/java/net/alawn/bill/config/SwaggerConfig.java b/src/main/java/net/alawn/bill/config/SwaggerConfig.java new file mode 100644 index 0000000..8d0bcc8 --- /dev/null +++ b/src/main/java/net/alawn/bill/config/SwaggerConfig.java @@ -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 securitySchemes() { + return newArrayList( + new ApiKey("Authorization", "Authorization", "header")); + } + + + private List securityContexts() { + return newArrayList( + SecurityContext.builder() + .securityReferences(defaultAuth()) + .forPaths(PathSelectors.regex("^(?!auth).*$")) + .build() + ); + } + List defaultAuth() { + AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything"); + AuthorizationScope[] authorizationScopes = new AuthorizationScope[1]; + authorizationScopes[0] = authorizationScope; + return newArrayList( + new SecurityReference("Authorization", authorizationScopes)); + } +} + diff --git a/src/main/java/net/alawn/bill/config/UserIDAuditorBean.java b/src/main/java/net/alawn/bill/config/UserIDAuditorBean.java new file mode 100644 index 0000000..42851d2 --- /dev/null +++ b/src/main/java/net/alawn/bill/config/UserIDAuditorBean.java @@ -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 { + + @Override + public Optional 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(); + } + } +} diff --git a/src/main/java/net/alawn/bill/controller/AuthController.java b/src/main/java/net/alawn/bill/controller/AuthController.java new file mode 100644 index 0000000..cef6bf7 --- /dev/null +++ b/src/main/java/net/alawn/bill/controller/AuthController.java @@ -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); + } +} diff --git a/src/main/java/net/alawn/bill/controller/BasicController.java b/src/main/java/net/alawn/bill/controller/BasicController.java new file mode 100644 index 0000000..19ec7d8 --- /dev/null +++ b/src/main/java/net/alawn/bill/controller/BasicController.java @@ -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 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 getPost(@PathVariable long id){ + log.info("post id:" + id); + + /** 登记 Post */ + Optional 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 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 getMerchant(@PathVariable long id){ + /** 登记 Post */ + Optional 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 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(); + } + } +} diff --git a/src/main/java/net/alawn/bill/controller/BillController.java b/src/main/java/net/alawn/bill/controller/BillController.java new file mode 100644 index 0000000..c5313ce --- /dev/null +++ b/src/main/java/net/alawn/bill/controller/BillController.java @@ -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); + } +} diff --git a/src/main/java/net/alawn/bill/entity/dto/AddBill.java b/src/main/java/net/alawn/bill/entity/dto/AddBill.java new file mode 100644 index 0000000..3dace38 --- /dev/null +++ b/src/main/java/net/alawn/bill/entity/dto/AddBill.java @@ -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; +} diff --git a/src/main/java/net/alawn/bill/entity/dto/AddMerchant.java b/src/main/java/net/alawn/bill/entity/dto/AddMerchant.java new file mode 100644 index 0000000..85d8405 --- /dev/null +++ b/src/main/java/net/alawn/bill/entity/dto/AddMerchant.java @@ -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(); + } +} diff --git a/src/main/java/net/alawn/bill/entity/dto/AddPost.java b/src/main/java/net/alawn/bill/entity/dto/AddPost.java new file mode 100644 index 0000000..6cacc67 --- /dev/null +++ b/src/main/java/net/alawn/bill/entity/dto/AddPost.java @@ -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(); + } +} diff --git a/src/main/java/net/alawn/bill/entity/dto/AddTitle.java b/src/main/java/net/alawn/bill/entity/dto/AddTitle.java new file mode 100644 index 0000000..351df7b --- /dev/null +++ b/src/main/java/net/alawn/bill/entity/dto/AddTitle.java @@ -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(); + } +} diff --git a/src/main/java/net/alawn/bill/entity/dto/AddUser.java b/src/main/java/net/alawn/bill/entity/dto/AddUser.java new file mode 100644 index 0000000..58376fe --- /dev/null +++ b/src/main/java/net/alawn/bill/entity/dto/AddUser.java @@ -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(); + } +} diff --git a/src/main/java/net/alawn/bill/entity/dto/BillItem.java b/src/main/java/net/alawn/bill/entity/dto/BillItem.java new file mode 100644 index 0000000..a5b489c --- /dev/null +++ b/src/main/java/net/alawn/bill/entity/dto/BillItem.java @@ -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; +} diff --git a/src/main/java/net/alawn/bill/entity/po/Authority.java b/src/main/java/net/alawn/bill/entity/po/Authority.java new file mode 100644 index 0000000..781000c --- /dev/null +++ b/src/main/java/net/alawn/bill/entity/po/Authority.java @@ -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; + } +} diff --git a/src/main/java/net/alawn/bill/entity/po/AuthorityId.java b/src/main/java/net/alawn/bill/entity/po/AuthorityId.java new file mode 100644 index 0000000..b984d2a --- /dev/null +++ b/src/main/java/net/alawn/bill/entity/po/AuthorityId.java @@ -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; + } +} diff --git a/src/main/java/net/alawn/bill/entity/po/Base.java b/src/main/java/net/alawn/bill/entity/po/Base.java new file mode 100644 index 0000000..f7a952e --- /dev/null +++ b/src/main/java/net/alawn/bill/entity/po/Base.java @@ -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; + + + +} diff --git a/src/main/java/net/alawn/bill/entity/po/Book.java b/src/main/java/net/alawn/bill/entity/po/Book.java new file mode 100644 index 0000000..631fe56 --- /dev/null +++ b/src/main/java/net/alawn/bill/entity/po/Book.java @@ -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; +} diff --git a/src/main/java/net/alawn/bill/entity/po/Item.java b/src/main/java/net/alawn/bill/entity/po/Item.java new file mode 100644 index 0000000..55028a8 --- /dev/null +++ b/src/main/java/net/alawn/bill/entity/po/Item.java @@ -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; +} diff --git a/src/main/java/net/alawn/bill/entity/po/Merchant.java b/src/main/java/net/alawn/bill/entity/po/Merchant.java new file mode 100644 index 0000000..df7c6de --- /dev/null +++ b/src/main/java/net/alawn/bill/entity/po/Merchant.java @@ -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; +} diff --git a/src/main/java/net/alawn/bill/entity/po/Post.java b/src/main/java/net/alawn/bill/entity/po/Post.java new file mode 100644 index 0000000..7dbd8ec --- /dev/null +++ b/src/main/java/net/alawn/bill/entity/po/Post.java @@ -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 ; +} diff --git a/src/main/java/net/alawn/bill/entity/po/Title.java b/src/main/java/net/alawn/bill/entity/po/Title.java new file mode 100644 index 0000000..8d88404 --- /dev/null +++ b/src/main/java/net/alawn/bill/entity/po/Title.java @@ -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; +} diff --git a/src/main/java/net/alawn/bill/entity/po/User.java b/src/main/java/net/alawn/bill/entity/po/User.java new file mode 100644 index 0000000..7f35854 --- /dev/null +++ b/src/main/java/net/alawn/bill/entity/po/User.java @@ -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()); +// } +} diff --git a/src/main/java/net/alawn/bill/enums/AccessProtocol.java b/src/main/java/net/alawn/bill/enums/AccessProtocol.java new file mode 100644 index 0000000..110e90a --- /dev/null +++ b/src/main/java/net/alawn/bill/enums/AccessProtocol.java @@ -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; + } +} diff --git a/src/main/java/net/alawn/bill/enums/State.java b/src/main/java/net/alawn/bill/enums/State.java new file mode 100644 index 0000000..676defc --- /dev/null +++ b/src/main/java/net/alawn/bill/enums/State.java @@ -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; + } +} diff --git a/src/main/java/net/alawn/bill/exception/CommonException.java b/src/main/java/net/alawn/bill/exception/CommonException.java new file mode 100644 index 0000000..c124934 --- /dev/null +++ b/src/main/java/net/alawn/bill/exception/CommonException.java @@ -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(); + } +} diff --git a/src/main/java/net/alawn/bill/exception/RespMsg.java b/src/main/java/net/alawn/bill/exception/RespMsg.java new file mode 100644 index 0000000..8bb6f23 --- /dev/null +++ b/src/main/java/net/alawn/bill/exception/RespMsg.java @@ -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; } + +} diff --git a/src/main/java/net/alawn/bill/exception/RespMsgConstants.java b/src/main/java/net/alawn/bill/exception/RespMsgConstants.java new file mode 100644 index 0000000..ef5cd2e --- /dev/null +++ b/src/main/java/net/alawn/bill/exception/RespMsgConstants.java @@ -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 = "业务成功" ; +} diff --git a/src/main/java/net/alawn/bill/exception/UserAlreadyExistException.java b/src/main/java/net/alawn/bill/exception/UserAlreadyExistException.java new file mode 100644 index 0000000..e978a46 --- /dev/null +++ b/src/main/java/net/alawn/bill/exception/UserAlreadyExistException.java @@ -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); + } +} diff --git a/src/main/java/net/alawn/bill/repository/AuthorityRepo.java b/src/main/java/net/alawn/bill/repository/AuthorityRepo.java new file mode 100644 index 0000000..d0de133 --- /dev/null +++ b/src/main/java/net/alawn/bill/repository/AuthorityRepo.java @@ -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> { +} diff --git a/src/main/java/net/alawn/bill/repository/BookRepo.java b/src/main/java/net/alawn/bill/repository/BookRepo.java new file mode 100644 index 0000000..e4c5b37 --- /dev/null +++ b/src/main/java/net/alawn/bill/repository/BookRepo.java @@ -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> { + +} diff --git a/src/main/java/net/alawn/bill/repository/ItemRepo.java b/src/main/java/net/alawn/bill/repository/ItemRepo.java new file mode 100644 index 0000000..c641762 --- /dev/null +++ b/src/main/java/net/alawn/bill/repository/ItemRepo.java @@ -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> { + +} diff --git a/src/main/java/net/alawn/bill/repository/MerchantRepo.java b/src/main/java/net/alawn/bill/repository/MerchantRepo.java new file mode 100644 index 0000000..e7cfa44 --- /dev/null +++ b/src/main/java/net/alawn/bill/repository/MerchantRepo.java @@ -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> { + +} diff --git a/src/main/java/net/alawn/bill/repository/PostRepo.java b/src/main/java/net/alawn/bill/repository/PostRepo.java new file mode 100644 index 0000000..473bdb3 --- /dev/null +++ b/src/main/java/net/alawn/bill/repository/PostRepo.java @@ -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> { + +} diff --git a/src/main/java/net/alawn/bill/repository/TitleRepo.java b/src/main/java/net/alawn/bill/repository/TitleRepo.java new file mode 100644 index 0000000..201ef01 --- /dev/null +++ b/src/main/java/net/alawn/bill/repository/TitleRepo.java @@ -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> { + +} diff --git a/src/main/java/net/alawn/bill/repository/UserRepo.java b/src/main/java/net/alawn/bill/repository/UserRepo.java new file mode 100644 index 0000000..a63bd27 --- /dev/null +++ b/src/main/java/net/alawn/bill/repository/UserRepo.java @@ -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); +} diff --git a/src/main/java/net/alawn/bill/security/AuthUser.java b/src/main/java/net/alawn/bill/security/AuthUser.java new file mode 100644 index 0000000..e4ac365 --- /dev/null +++ b/src/main/java/net/alawn/bill/security/AuthUser.java @@ -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; + } + + +} diff --git a/src/main/java/net/alawn/bill/security/AuthUserDetailsServiceImpl.java b/src/main/java/net/alawn/bill/security/AuthUserDetailsServiceImpl.java new file mode 100644 index 0000000..c962a4a --- /dev/null +++ b/src/main/java/net/alawn/bill/security/AuthUserDetailsServiceImpl.java @@ -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); + } + } +} diff --git a/src/main/java/net/alawn/bill/security/JwtAuthenticationEntryPoint.java b/src/main/java/net/alawn/bill/security/JwtAuthenticationEntryPoint.java new file mode 100644 index 0000000..69b478d --- /dev/null +++ b/src/main/java/net/alawn/bill/security/JwtAuthenticationEntryPoint.java @@ -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"); + } +} diff --git a/src/main/java/net/alawn/bill/security/JwtAuthenticationRequest.java b/src/main/java/net/alawn/bill/security/JwtAuthenticationRequest.java new file mode 100644 index 0000000..af289b2 --- /dev/null +++ b/src/main/java/net/alawn/bill/security/JwtAuthenticationRequest.java @@ -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; +} diff --git a/src/main/java/net/alawn/bill/security/JwtAuthenticationResponse.java b/src/main/java/net/alawn/bill/security/JwtAuthenticationResponse.java new file mode 100644 index 0000000..9ddcf11 --- /dev/null +++ b/src/main/java/net/alawn/bill/security/JwtAuthenticationResponse.java @@ -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; + } + +} diff --git a/src/main/java/net/alawn/bill/security/JwtAuthenticationTokenFilter.java b/src/main/java/net/alawn/bill/security/JwtAuthenticationTokenFilter.java new file mode 100644 index 0000000..7737bc3 --- /dev/null +++ b/src/main/java/net/alawn/bill/security/JwtAuthenticationTokenFilter.java @@ -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); + } +} + diff --git a/src/main/java/net/alawn/bill/security/JwtTokenUtil.java b/src/main/java/net/alawn/bill/security/JwtTokenUtil.java new file mode 100644 index 0000000..eeba732 --- /dev/null +++ b/src/main/java/net/alawn/bill/security/JwtTokenUtil.java @@ -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; + } +} diff --git a/src/main/java/net/alawn/bill/security/UserFactory.java b/src/main/java/net/alawn/bill/security/UserFactory.java new file mode 100644 index 0000000..9298890 --- /dev/null +++ b/src/main/java/net/alawn/bill/security/UserFactory.java @@ -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()); +// } +} diff --git a/src/main/java/net/alawn/bill/security/WebSecurityConfig.java b/src/main/java/net/alawn/bill/security/WebSecurityConfig.java new file mode 100644 index 0000000..e7c8a30 --- /dev/null +++ b/src/main/java/net/alawn/bill/security/WebSecurityConfig.java @@ -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)); +// } + +} diff --git a/src/main/java/net/alawn/bill/service/AuthService.java b/src/main/java/net/alawn/bill/service/AuthService.java new file mode 100644 index 0000000..185dc69 --- /dev/null +++ b/src/main/java/net/alawn/bill/service/AuthService.java @@ -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); +} diff --git a/src/main/java/net/alawn/bill/service/impl/AuthServiceImpl.java b/src/main/java/net/alawn/bill/service/impl/AuthServiceImpl.java new file mode 100644 index 0000000..76594a2 --- /dev/null +++ b/src/main/java/net/alawn/bill/service/impl/AuthServiceImpl.java @@ -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); + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 0000000..5335a00 --- /dev/null +++ b/src/main/resources/application.properties @@ -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 +