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 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 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 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