diff --git a/pom.xml b/pom.xml
index 031c896..fb26856 100644
--- a/pom.xml
+++ b/pom.xml
@@ -50,6 +50,11 @@
mybatis-plus-boot-starter
3.5.3
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
org.springframework.boot
spring-boot-starter-test
diff --git a/src/main/java/com/iflytop/nuclear/NuclearApplication.java b/src/main/java/com/iflytop/nuclear/NuclearApplication.java
index 5293f45..50da635 100644
--- a/src/main/java/com/iflytop/nuclear/NuclearApplication.java
+++ b/src/main/java/com/iflytop/nuclear/NuclearApplication.java
@@ -1,15 +1,22 @@
package com.iflytop.nuclear;
import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.Banner;
+import org.springframework.boot.ResourceBanner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.core.io.ClassPathResource;
@SpringBootApplication
-@MapperScan("com.iflytop.boditech.mapper")
+@MapperScan("com.iflytop.nuclear.mapper")
public class NuclearApplication {
public static void main(String[] args) {
- SpringApplication.run(NuclearApplication.class, args);
+ SpringApplicationBuilder builder = new SpringApplicationBuilder(NuclearApplication.class);
+ builder.bannerMode(Banner.Mode.CONSOLE);
+ builder.banner(new ResourceBanner(new ClassPathResource("banner.txt")));
+ builder.run(args);
}
}
diff --git a/src/main/java/com/iflytop/nuclear/config/SecurityConfig.java b/src/main/java/com/iflytop/nuclear/config/SecurityConfig.java
new file mode 100644
index 0000000..ef3fb7a
--- /dev/null
+++ b/src/main/java/com/iflytop/nuclear/config/SecurityConfig.java
@@ -0,0 +1,68 @@
+package com.iflytop.nuclear.config;
+
+import com.iflytop.nuclear.exception.JWTAccessDeniedHandler;
+import com.iflytop.nuclear.exception.JWTAuthenticationEntryPoint;
+import com.iflytop.nuclear.filter.JWTAuthenticationFilter;
+import com.iflytop.nuclear.filter.JWTAuthorizationFilter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.context.annotation.Bean;
+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.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.web.cors.CorsConfiguration;
+import org.springframework.web.cors.CorsConfigurationSource;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+
+/**
+ * @author cool
+ * @desc spring-security 配置类
+ */
+@EnableWebSecurity
+@EnableGlobalMethodSecurity(prePostEnabled = true)
+public class SecurityConfig extends WebSecurityConfigurerAdapter {
+
+ @Autowired
+ @Qualifier("userDetailsServiceImpl")
+ private UserDetailsService userDetailsService;
+
+ @Bean
+ public BCryptPasswordEncoder bCryptPasswordEncoder() {
+ return new BCryptPasswordEncoder();
+ }
+
+ @Override
+ protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+ auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
+ }
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ http.cors().and().csrf().disable()
+ .authorizeRequests()
+ // 注册接口,需要ADMIN用户才能访问
+ .antMatchers("/account/register").hasRole("ADMIN")
+ // 其他都放行了
+ .anyRequest().permitAll()
+ .and()
+ .addFilter(new JWTAuthenticationFilter(authenticationManager()))
+ .addFilter(new JWTAuthorizationFilter(authenticationManager()))
+ // 不需要session
+ .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
+ .and()
+ .exceptionHandling().authenticationEntryPoint(new JWTAuthenticationEntryPoint())
+ .accessDeniedHandler(new JWTAccessDeniedHandler()); //添加无权限时的处理
+ }
+
+ @Bean
+ CorsConfigurationSource corsConfigurationSource() {
+ final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
+ return source;
+ }
+}
diff --git a/src/main/java/com/iflytop/nuclear/controller/AccountController.java b/src/main/java/com/iflytop/nuclear/controller/AccountController.java
new file mode 100755
index 0000000..ebb3260
--- /dev/null
+++ b/src/main/java/com/iflytop/nuclear/controller/AccountController.java
@@ -0,0 +1,56 @@
+package com.iflytop.nuclear.controller;
+
+import com.iflytop.nuclear.model.Account;
+import com.iflytop.nuclear.service.AccountService;
+import com.iflytop.nuclear.utils.ResponseData;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author cool
+ * @desc 用户接口
+ */
+@Slf4j
+@RestController
+@RequestMapping("/account")
+public class AccountController {
+
+ @Autowired
+ AccountService accountService;
+
+ /**
+ * 查询用户列表
+ * @return
+ */
+ @GetMapping("/list")
+ public ResponseData getAccountList() {
+ log.info("-----------------查询账户列表开始-----------------");
+ // 筛除password
+ // TODO
+ List accounts = accountService.list();
+ log.info("-----------------查询账户列表结束-----------------");
+ return ResponseData.success(accounts);
+ }
+
+ /**
+ * 注册接口,需要有ADMIN权限
+ * @param registerUser
+ * @return
+ */
+ @PostMapping("/register")
+ @PreAuthorize("hasRole('ADMIN')")
+ public ResponseData registerAccount(@RequestBody Map registerUser) {
+ log.info("-----------------注册账户开始-----------------");
+ boolean register = accountService.register(registerUser.get("username"), registerUser.get("password"));
+ if (register) {
+ log.info("-----------------注册账户成功-----------------");
+ return ResponseData.success();
+ }
+ return ResponseData.fail("注册失败");
+ }
+}
diff --git a/src/main/java/com/iflytop/nuclear/entity/JwtUser.java b/src/main/java/com/iflytop/nuclear/entity/JwtUser.java
new file mode 100644
index 0000000..83c942e
--- /dev/null
+++ b/src/main/java/com/iflytop/nuclear/entity/JwtUser.java
@@ -0,0 +1,80 @@
+package com.iflytop.nuclear.entity;
+
+import com.iflytop.nuclear.model.Account;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * @author cool
+ * @desc 自定义实现UserDetails
+ */
+public class JwtUser implements UserDetails {
+
+ private Long id;
+ private String username;
+ private String password;
+ private Collection extends GrantedAuthority> authorities;
+
+ public JwtUser() {
+ }
+
+ // 写一个能直接使用user创建jwtUser的构造器
+ public JwtUser(Account user) {
+ id = user.getId();
+ username = user.getUsername();
+ password = user.getPassword();
+ authorities = Collections.singleton(new SimpleGrantedAuthority(user.getRole()));
+ }
+
+ @Override
+ public Collection extends GrantedAuthority> getAuthorities() {
+ return authorities;
+ }
+
+ @Override
+ public String getPassword() {
+ return password;
+ }
+
+ @Override
+ public String getUsername() {
+ return username;
+ }
+
+ // 账号是否未过期
+ @Override
+ public boolean isAccountNonExpired() {
+ return true;
+ }
+
+ // 账号是否未锁定
+ @Override
+ public boolean isAccountNonLocked() {
+ return true;
+ }
+
+ // 账号凭证是否未过期
+ @Override
+ public boolean isCredentialsNonExpired() {
+ return true;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "JwtUser{" +
+ "id=" + id +
+ ", username='" + username + '\'' +
+ ", password='" + password + '\'' +
+ ", authorities=" + authorities +
+ '}';
+ }
+}
diff --git a/src/main/java/com/iflytop/nuclear/exception/JWTAccessDeniedHandler.java b/src/main/java/com/iflytop/nuclear/exception/JWTAccessDeniedHandler.java
new file mode 100644
index 0000000..a0a2723
--- /dev/null
+++ b/src/main/java/com/iflytop/nuclear/exception/JWTAccessDeniedHandler.java
@@ -0,0 +1,25 @@
+package com.iflytop.nuclear.exception;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.web.access.AccessDeniedHandler;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * @author cool
+ * @description: 没有访问权限
+ */
+public class JWTAccessDeniedHandler implements AccessDeniedHandler {
+ @Override
+ public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
+ httpServletResponse.setCharacterEncoding("UTF-8");
+ httpServletResponse.setContentType("application/json; charset=utf-8");
+ httpServletResponse.setStatus(HttpServletResponse.SC_FORBIDDEN);
+ String reason = "统一处理,原因:" + e.getMessage();
+ httpServletResponse.getWriter().write(new ObjectMapper().writeValueAsString(reason));
+ }
+}
diff --git a/src/main/java/com/iflytop/nuclear/exception/JWTAuthenticationEntryPoint.java b/src/main/java/com/iflytop/nuclear/exception/JWTAuthenticationEntryPoint.java
new file mode 100644
index 0000000..c1cb110
--- /dev/null
+++ b/src/main/java/com/iflytop/nuclear/exception/JWTAuthenticationEntryPoint.java
@@ -0,0 +1,28 @@
+package com.iflytop.nuclear.exception;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.AuthenticationEntryPoint;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * @author cool
+ * @description: 没有携带token或者token无效
+ */
+public class JWTAuthenticationEntryPoint implements AuthenticationEntryPoint {
+ @Override
+ public void commence(HttpServletRequest request,
+ HttpServletResponse response,
+ AuthenticationException authException) throws IOException, ServletException {
+
+ response.setCharacterEncoding("UTF-8");
+ response.setContentType("application/json; charset=utf-8");
+ response.setStatus(HttpServletResponse.SC_FORBIDDEN);
+ String reason = "统一处理,原因:" + authException.getMessage();
+ response.getWriter().write(new ObjectMapper().writeValueAsString(reason));
+ }
+}
diff --git a/src/main/java/com/iflytop/nuclear/exception/TokenIsExpiredException.java b/src/main/java/com/iflytop/nuclear/exception/TokenIsExpiredException.java
new file mode 100644
index 0000000..1959eb9
--- /dev/null
+++ b/src/main/java/com/iflytop/nuclear/exception/TokenIsExpiredException.java
@@ -0,0 +1,27 @@
+package com.iflytop.nuclear.exception;
+
+/**
+ * @author cool
+ * @description: 自定义异常
+ */
+public class TokenIsExpiredException extends Exception {
+
+ public TokenIsExpiredException() {
+ }
+
+ public TokenIsExpiredException(String message) {
+ super(message);
+ }
+
+ public TokenIsExpiredException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public TokenIsExpiredException(Throwable cause) {
+ super(cause);
+ }
+
+ public TokenIsExpiredException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ }
+}
diff --git a/src/main/java/com/iflytop/nuclear/filter/JWTAuthenticationFilter.java b/src/main/java/com/iflytop/nuclear/filter/JWTAuthenticationFilter.java
new file mode 100644
index 0000000..f2cd636
--- /dev/null
+++ b/src/main/java/com/iflytop/nuclear/filter/JWTAuthenticationFilter.java
@@ -0,0 +1,77 @@
+package com.iflytop.nuclear.filter;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.iflytop.nuclear.entity.JwtUser;
+import com.iflytop.nuclear.model.Account;
+import com.iflytop.nuclear.utils.JwtTokenUtils;
+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.GrantedAuthority;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * @author cool
+ * @desc 该过滤器用于获取用户登录的信息
+ */
+public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
+
+ private AuthenticationManager authenticationManager;
+
+ public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
+ this.authenticationManager = authenticationManager;
+ super.setFilterProcessesUrl("/account/login");
+ }
+
+ @Override
+ public Authentication attemptAuthentication(HttpServletRequest request,
+ HttpServletResponse response) throws AuthenticationException {
+
+ // 从输入流中获取到登录的信息
+ try {
+ Account loginUser = new ObjectMapper().readValue(request.getInputStream(), Account.class);
+ return authenticationManager.authenticate(
+ new UsernamePasswordAuthenticationToken(loginUser.getUsername(), loginUser.getPassword(), new ArrayList<>())
+ );
+ } catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ // 成功验证后调用的方法
+ // 如果验证成功,就生成token并返回
+ @Override
+ protected void successfulAuthentication(HttpServletRequest request,
+ HttpServletResponse response,
+ FilterChain chain,
+ Authentication authResult) throws IOException, ServletException {
+
+ JwtUser jwtUser = (JwtUser) authResult.getPrincipal();
+ System.out.println("jwtUser:" + jwtUser.toString());
+ String role = "";
+ Collection extends GrantedAuthority> authorities = jwtUser.getAuthorities();
+ for (GrantedAuthority authority : authorities){
+ role = authority.getAuthority();
+ }
+ String token = JwtTokenUtils.createToken(jwtUser.getUsername(), role);
+ // 返回创建成功的token
+ // 但是这里创建的token只是单纯的token
+ // 按照jwt的规定,最后请求的时候应该是 `Bearer token`
+ response.setHeader("token", JwtTokenUtils.TOKEN_PREFIX + token);
+ }
+
+ @Override
+ protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
+ response.getWriter().write("authentication failed, reason: " + failed.getMessage());
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/iflytop/nuclear/filter/JWTAuthorizationFilter.java b/src/main/java/com/iflytop/nuclear/filter/JWTAuthorizationFilter.java
new file mode 100644
index 0000000..8ffdaef
--- /dev/null
+++ b/src/main/java/com/iflytop/nuclear/filter/JWTAuthorizationFilter.java
@@ -0,0 +1,73 @@
+package com.iflytop.nuclear.filter;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.iflytop.nuclear.exception.TokenIsExpiredException;
+import com.iflytop.nuclear.utils.JwtTokenUtils;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.Collections;
+
+/**
+ * @author cool
+ * @desc 鉴权
+ */
+public class JWTAuthorizationFilter extends BasicAuthenticationFilter {
+
+ public JWTAuthorizationFilter(AuthenticationManager authenticationManager) {
+ super(authenticationManager);
+ }
+
+ @Override
+ protected void doFilterInternal(HttpServletRequest request,
+ HttpServletResponse response,
+ FilterChain chain) throws IOException, ServletException {
+
+ String tokenHeader = request.getHeader(JwtTokenUtils.TOKEN_HEADER);
+ // 如果请求头中没有Authorization信息则直接放行了
+ if (tokenHeader == null || !tokenHeader.startsWith(JwtTokenUtils.TOKEN_PREFIX)) {
+ chain.doFilter(request, response);
+ return;
+ }
+ // 如果请求头中有token,则进行解析,并且设置认证信息
+ try {
+ SecurityContextHolder.getContext().setAuthentication(getAuthentication(tokenHeader));
+ } catch (TokenIsExpiredException e) {
+ //返回json形式的错误信息
+ response.setCharacterEncoding("UTF-8");
+ response.setContentType("application/json; charset=utf-8");
+ response.setStatus(HttpServletResponse.SC_FORBIDDEN);
+ String reason = "统一处理,原因:" + e.getMessage();
+ response.getWriter().write(new ObjectMapper().writeValueAsString(reason));
+ response.getWriter().flush();
+ return;
+ }
+ super.doFilterInternal(request, response, chain);
+ }
+
+ // 这里从token中获取用户信息并新建一个token
+ private UsernamePasswordAuthenticationToken getAuthentication(String tokenHeader) throws TokenIsExpiredException {
+ String token = tokenHeader.replace(JwtTokenUtils.TOKEN_PREFIX, "");
+ boolean expiration = JwtTokenUtils.isExpiration(token);
+ if (expiration) {
+ throw new TokenIsExpiredException("token超时了");
+ } else {
+ String username = JwtTokenUtils.getUsername(token);
+ String role = JwtTokenUtils.getUserRole(token);
+ if (username != null) {
+ return new UsernamePasswordAuthenticationToken(username, null,
+ Collections.singleton(new SimpleGrantedAuthority(role))
+ );
+ }
+ }
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/iflytop/nuclear/mapper/AccountMapper.java b/src/main/java/com/iflytop/nuclear/mapper/AccountMapper.java
new file mode 100755
index 0000000..856607b
--- /dev/null
+++ b/src/main/java/com/iflytop/nuclear/mapper/AccountMapper.java
@@ -0,0 +1,13 @@
+package com.iflytop.nuclear.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.iflytop.nuclear.model.Account;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * @author cool
+ */
+@Mapper
+public interface AccountMapper extends BaseMapper {
+
+}
diff --git a/src/main/java/com/iflytop/nuclear/model/Account.java b/src/main/java/com/iflytop/nuclear/model/Account.java
new file mode 100755
index 0000000..cda0eb2
--- /dev/null
+++ b/src/main/java/com/iflytop/nuclear/model/Account.java
@@ -0,0 +1,26 @@
+package com.iflytop.nuclear.model;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author cool
+ * @desc 账户model
+ */
+@Data
+@TableName("account")
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class Account {
+ @TableId
+ private Long id;
+ private String username;
+ private String password;
+ private String role;
+ private String nickname;
+}
diff --git a/src/main/java/com/iflytop/nuclear/service/AccountService.java b/src/main/java/com/iflytop/nuclear/service/AccountService.java
new file mode 100755
index 0000000..9acd175
--- /dev/null
+++ b/src/main/java/com/iflytop/nuclear/service/AccountService.java
@@ -0,0 +1,16 @@
+package com.iflytop.nuclear.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.iflytop.nuclear.model.Account;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * @author cool
+ */
+@Transactional
+public interface AccountService extends IService {
+
+ boolean register(String username, String password);
+
+ Account findByUsername(String username);
+}
diff --git a/src/main/java/com/iflytop/nuclear/service/UserDetailsServiceImpl.java b/src/main/java/com/iflytop/nuclear/service/UserDetailsServiceImpl.java
new file mode 100644
index 0000000..a2becd0
--- /dev/null
+++ b/src/main/java/com/iflytop/nuclear/service/UserDetailsServiceImpl.java
@@ -0,0 +1,28 @@
+package com.iflytop.nuclear.service;
+
+import com.iflytop.nuclear.entity.JwtUser;
+import com.iflytop.nuclear.model.Account;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
+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 cool
+ * @desc 使用springSecurity需要实现UserDetailsService接口供权限框架调用
+ */
+@Service
+public class UserDetailsServiceImpl implements UserDetailsService {
+
+ @Autowired
+ @Lazy
+ AccountService accountService;
+
+ @Override
+ public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
+ Account user = accountService.findByUsername(username);
+ return new JwtUser(user);
+ }
+}
diff --git a/src/main/java/com/iflytop/nuclear/service/impl/AccountServiceImpl.java b/src/main/java/com/iflytop/nuclear/service/impl/AccountServiceImpl.java
new file mode 100755
index 0000000..529d394
--- /dev/null
+++ b/src/main/java/com/iflytop/nuclear/service/impl/AccountServiceImpl.java
@@ -0,0 +1,51 @@
+package com.iflytop.nuclear.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.iflytop.nuclear.mapper.AccountMapper;
+import com.iflytop.nuclear.model.Account;
+import com.iflytop.nuclear.service.AccountService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author cool
+ */
+@Service
+public class AccountServiceImpl extends ServiceImpl implements AccountService {
+
+ @Autowired
+ @Lazy
+ private BCryptPasswordEncoder bCryptPasswordEncoder;
+
+ /**
+ * 注册用户
+ * @param username
+ * @param password
+ * @return
+ */
+ @Override
+ public boolean register(String username, String password) {
+ Account account = Account.builder()
+ .username(username)
+ .password(bCryptPasswordEncoder.encode(password))
+ .role("ROLE_USER")
+ .build();
+ return this.save(account);
+ }
+
+ /**
+ * 根据用户名查找用户
+ * @param username
+ * @return
+ */
+ @Override
+ public Account findByUsername(String username) {
+ QueryWrapper accountQueryWrapper = new QueryWrapper<>();
+ accountQueryWrapper.eq("username", username);
+ Account account = this.getOne(accountQueryWrapper);
+ return account;
+ }
+}
diff --git a/src/main/java/com/iflytop/nuclear/utils/JwtTokenUtils.java b/src/main/java/com/iflytop/nuclear/utils/JwtTokenUtils.java
new file mode 100644
index 0000000..2bfd9b2
--- /dev/null
+++ b/src/main/java/com/iflytop/nuclear/utils/JwtTokenUtils.java
@@ -0,0 +1,68 @@
+package com.iflytop.nuclear.utils;
+
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.ExpiredJwtException;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+
+import java.util.Date;
+import java.util.HashMap;
+
+/**
+ * @author cool
+ * @desc 操作jwt token 的工具类
+ */
+public class JwtTokenUtils {
+
+ public static final String TOKEN_HEADER = "Authorization";
+ public static final String TOKEN_PREFIX = "Bearer ";
+
+ private static final String SECRET = "eyJhbGciOiJIUzUxMiJ9.eyJleHAiOjE2NDg5ODg1MjAsInN1YiI6ImFkbWluIiwiY3JlYXR";
+ private static final String ISS = "iflytop";
+
+ // 角色的key
+ private static final String ROLE_CLAIMS = "rol";
+
+ // 过期时间是3600秒,既是1个小时
+ private static final long EXPIRATION = 3600L;
+
+ // 创建token
+ public static String createToken(String username, String role) {
+ HashMap map = new HashMap<>();
+ map.put(ROLE_CLAIMS, role);
+ return Jwts.builder()
+ .signWith(SignatureAlgorithm.HS512, SECRET)
+ .setClaims(map)
+ .setIssuer(ISS)
+ .setSubject(username)
+ .setIssuedAt(new Date())
+ .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION * 1000))
+ .compact();
+ }
+
+ // 从token中获取用户名
+ public static String getUsername(String token){
+ return getTokenBody(token).getSubject();
+ }
+
+ // 获取用户角色
+ public static String getUserRole(String token){
+ return (String) getTokenBody(token).get(ROLE_CLAIMS);
+ }
+
+ // 是否已过期
+ public static boolean isExpiration(String token) {
+ try {
+ return getTokenBody(token).getExpiration().before(new Date());
+ } catch (ExpiredJwtException e) {
+ return true;
+ }
+ }
+
+ private static Claims getTokenBody(String token){
+ return Jwts.parser()
+ .setSigningKey(SECRET)
+ .parseClaimsJws(token)
+ .getBody();
+ }
+}
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
index 83025f7..a37cd9e 100644
--- a/src/main/resources/application-dev.yml
+++ b/src/main/resources/application-dev.yml
@@ -1,7 +1,7 @@
spring:
datasource:
- url: jdbc:mysql://127.0.0.1:3306/boditech?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
+ url: jdbc:mysql://127.0.0.1:3306/nuclear?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
username: root
password: root
driverClassName: com.mysql.cj.jdbc.Driver
\ No newline at end of file