parent
d923ecf1f5
commit
89a243d86d
@ -1,5 +1,52 @@
|
|||||||
package com.shangping.backend.config;
|
package com.shangping.backend.config;
|
||||||
|
|
||||||
public class SecurityConfig {
|
import com.shangping.backend.config.filter.JwtAuthenticationTokenFilter;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.http.HttpMethod;
|
||||||
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
|
import org.springframework.security.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.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||||
|
|
||||||
}
|
@Configuration
|
||||||
|
@EnableWebSecurity
|
||||||
|
public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||||
|
@Autowired
|
||||||
|
private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public PasswordEncoder passwordEncoder() {
|
||||||
|
return new BCryptPasswordEncoder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@Override
|
||||||
|
public AuthenticationManager authenticationManagerBean() throws Exception {
|
||||||
|
return super.authenticationManagerBean();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
|
http.csrf().disable()
|
||||||
|
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
||||||
|
.and()
|
||||||
|
.authorizeRequests()
|
||||||
|
.antMatchers("/user/token", "/user/register").permitAll()
|
||||||
|
.antMatchers("/pk/start/game/", "/pk/receive/bot/move/").hasIpAddress("127.0.0.1")
|
||||||
|
.antMatchers(HttpMethod.OPTIONS).permitAll()
|
||||||
|
.anyRequest().authenticated();
|
||||||
|
|
||||||
|
http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void configure(WebSecurity web) throws Exception {
|
||||||
|
web.ignoring().antMatchers("/websocket/**");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
package com.shangping.backend.config.filter;
|
||||||
|
|
||||||
|
import com.shangping.backend.mapper.UserMapper;
|
||||||
|
import com.shangping.backend.pojo.User;
|
||||||
|
import com.shangping.backend.service.impl.utils.UserDetailsImpl;
|
||||||
|
import com.shangping.backend.utils.JwtUtil;
|
||||||
|
import io.jsonwebtoken.Claims;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
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;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
|
||||||
|
@Autowired
|
||||||
|
private UserMapper userMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doFilterInternal(HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull FilterChain filterChain) throws ServletException, IOException {
|
||||||
|
String token = request.getHeader("Authorization");
|
||||||
|
|
||||||
|
if (!StringUtils.hasText(token) || !token.startsWith("Bearer ")) {
|
||||||
|
filterChain.doFilter(request, response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
token = token.substring(7);
|
||||||
|
|
||||||
|
String userid;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Claims claims = JwtUtil.parseJWT(token);
|
||||||
|
userid = claims.getSubject();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
User user = userMapper.selectById(Integer.parseInt(userid));
|
||||||
|
|
||||||
|
if (user == null) {
|
||||||
|
throw new RuntimeException("用户名未登录");
|
||||||
|
}
|
||||||
|
|
||||||
|
UserDetailsImpl loginUser = new UserDetailsImpl(user);
|
||||||
|
UsernamePasswordAuthenticationToken authenticationToken =
|
||||||
|
new UsernamePasswordAuthenticationToken(loginUser, null, null);
|
||||||
|
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
|
||||||
|
|
||||||
|
filterChain.doFilter(request, response);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package com.shangping.backend.controller.user;
|
||||||
|
|
||||||
|
import com.shangping.backend.service.user.LoginService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
public class LoginController {
|
||||||
|
@Autowired
|
||||||
|
private LoginService loginService;
|
||||||
|
|
||||||
|
@PostMapping("/user/token/")
|
||||||
|
public Map<String, String> getToken(@RequestParam Map<String, String> map) {
|
||||||
|
String username = map.get("username");
|
||||||
|
String password = map.get("password");
|
||||||
|
return loginService.getToken(username, password);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
package com.shangping.backend.controller.user;
|
||||||
|
|
||||||
|
import com.shangping.backend.service.user.RegisterService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
public class RegisterController {
|
||||||
|
@Autowired
|
||||||
|
private RegisterService registerService;
|
||||||
|
|
||||||
|
@PostMapping("/user/register")
|
||||||
|
public Map<String, String> register(@RequestBody Map<String, String> map){
|
||||||
|
|
||||||
|
System.out.println("map: " + map);
|
||||||
|
|
||||||
|
String account = map.get("account");
|
||||||
|
String password = map.get("password");
|
||||||
|
String confirmedPassword = map.get("confirmedPassword");
|
||||||
|
String identity = map.get("identity");
|
||||||
|
|
||||||
|
return registerService.register(account, password, confirmedPassword, identity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,4 @@
|
|||||||
|
package com.shangping.backend.mapper;
|
||||||
|
|
||||||
|
public interface InvoiceMapper {
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
package com.shangping.backend.mapper;
|
||||||
|
|
||||||
|
public interface OrderMapper {
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
package com.shangping.backend.mapper;
|
||||||
|
|
||||||
|
public interface ReimbursementMapper {
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
package com.shangping.backend.mapper;
|
||||||
|
|
||||||
|
public interface StockMapper {
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.shangping.backend.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.shangping.backend.pojo.User;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface UserMapper extends BaseMapper<User> {
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
package com.shangping.backend.pojo;
|
||||||
|
|
||||||
|
public class Invoice {
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
package com.shangping.backend.pojo;
|
||||||
|
|
||||||
|
public class Order {
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
package com.shangping.backend.pojo;
|
||||||
|
|
||||||
|
public class Reimbursement {
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
package com.shangping.backend.pojo;
|
||||||
|
|
||||||
|
public class Stock {
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package com.shangping.backend.pojo;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class User {
|
||||||
|
private String account;
|
||||||
|
private String nickname;
|
||||||
|
private String password;
|
||||||
|
private String identity;
|
||||||
|
private String photo;
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package com.shangping.backend.service.impl.user;
|
||||||
|
|
||||||
|
import com.shangping.backend.pojo.User;
|
||||||
|
import com.shangping.backend.service.impl.utils.UserDetailsImpl;
|
||||||
|
import com.shangping.backend.service.user.LoginService;
|
||||||
|
import com.shangping.backend.utils.JwtUtil;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class LoginServiceImpl implements LoginService {
|
||||||
|
@Autowired
|
||||||
|
private AuthenticationManager authenticationManager;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getToken(String account, String password){
|
||||||
|
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(account, password);
|
||||||
|
|
||||||
|
Authentication authenticate = authenticationManager.authenticate(authenticationToken); //登录失败会自动处理
|
||||||
|
|
||||||
|
UserDetailsImpl loginUser = (UserDetailsImpl) authenticate.getPrincipal();
|
||||||
|
User user = loginUser.getUser();
|
||||||
|
|
||||||
|
String jwt = JwtUtil.createJWT(user.getAccount().toString());
|
||||||
|
|
||||||
|
Map<String, String> map = new HashMap<>();
|
||||||
|
map.put("error_message", "success");
|
||||||
|
map.put("token", jwt);
|
||||||
|
|
||||||
|
return map;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,84 @@
|
|||||||
|
package com.shangping.backend.service.impl.user;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.shangping.backend.mapper.UserMapper;
|
||||||
|
import com.shangping.backend.pojo.User;
|
||||||
|
import com.shangping.backend.service.user.RegisterService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class RegisterServiceImpl implements RegisterService {
|
||||||
|
@Autowired
|
||||||
|
private UserMapper userMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PasswordEncoder passwordEncoder;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> register(String account, String password, String confirmedpassword, String identity) {
|
||||||
|
Map<String, String> map = new HashMap<>();
|
||||||
|
|
||||||
|
// System.out.println("account_impl: " + account);
|
||||||
|
// System.out.println("password_impl: " + password);
|
||||||
|
// System.out.println("confirmedpassword_impl: " + confirmedpassword);
|
||||||
|
// System.out.println("identity_impl: " + identity);
|
||||||
|
|
||||||
|
if (account == null) {
|
||||||
|
map.put("error_message", "用户名不能为空");
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (password == null || confirmedpassword == null){
|
||||||
|
map.put("error_message", "密码不能为空");
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
account = account.trim();
|
||||||
|
if (account.length() == 0){
|
||||||
|
map.put("error_message", "用户名不能为空");
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (password.length() == 0 || confirmedpassword.length() == 0){
|
||||||
|
map.put("error_message", "密码不能为空");
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (account.length() > 20){
|
||||||
|
map.put("error_message", "用户名长度不能大于20");
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
if(password.length() > 10 ||confirmedpassword.length() > 10){
|
||||||
|
map.put("error_message", "密码长度不能大于10");
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!password.equals(confirmedpassword)){
|
||||||
|
map.put("error_message", "两次输入的密码不一致");
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
|
||||||
|
queryWrapper.eq("account", account);
|
||||||
|
List<User> users = userMapper.selectList(queryWrapper);
|
||||||
|
if(!users.isEmpty()){
|
||||||
|
map.put("error_message", "用户名已存在");
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
String encodedPassword = passwordEncoder.encode(password);
|
||||||
|
String photo = "https://cdn.acwing.com/media/user/profile/photo/81680_lg_6a90272086.jpg";
|
||||||
|
String nickname = "用户" + account.toString();
|
||||||
|
User user = new User(account, nickname, encodedPassword, identity, photo);
|
||||||
|
userMapper.insert(user);
|
||||||
|
map.put("code", "200");
|
||||||
|
map.put("error_message", "success");
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
package com.shangping.backend.service.impl.utils;
|
||||||
|
|
||||||
|
import com.shangping.backend.pojo.User;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class UserDetailsImpl implements UserDetails {
|
||||||
|
|
||||||
|
private User user;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPassword() {
|
||||||
|
return user.getPassword();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUsername() {
|
||||||
|
return user.getAccount();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAccountNonExpired() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAccountNonLocked() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCredentialsNonExpired() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.shangping.backend.service.user;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface LoginService {
|
||||||
|
public Map<String, String> getToken(String account, String password);
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
package com.shangping.backend.service.user;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface RegisterService {
|
||||||
|
|
||||||
|
public Map<String, String> register(String account, String password, String confirmedpassword, String indentity);
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
package com.shangping.backend.utils;
|
||||||
|
|
||||||
|
import io.jsonwebtoken.Claims;
|
||||||
|
import io.jsonwebtoken.JwtBuilder;
|
||||||
|
import io.jsonwebtoken.Jwts;
|
||||||
|
import io.jsonwebtoken.SignatureAlgorithm;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.crypto.SecretKey;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
import java.util.Base64;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class JwtUtil {
|
||||||
|
public static final long JWT_TTL = 60 * 60 * 1000L * 24 * 14; // 有效期14天
|
||||||
|
public static final String JWT_KEY = "SDFGjhdsfalshdfHFdsjkdsfds121232131afasdfac";
|
||||||
|
|
||||||
|
public static String getUUID() {
|
||||||
|
return UUID.randomUUID().toString().replaceAll("-", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String createJWT(String subject) {
|
||||||
|
JwtBuilder builder = getJwtBuilder(subject, null, getUUID());
|
||||||
|
return builder.compact();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JwtBuilder getJwtBuilder(String subject, Long ttlMillis, String uuid) {
|
||||||
|
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
|
||||||
|
SecretKey secretKey = generalKey();
|
||||||
|
long nowMillis = System.currentTimeMillis();
|
||||||
|
Date now = new Date(nowMillis);
|
||||||
|
if (ttlMillis == null) {
|
||||||
|
ttlMillis = JwtUtil.JWT_TTL;
|
||||||
|
}
|
||||||
|
|
||||||
|
long expMillis = nowMillis + ttlMillis;
|
||||||
|
Date expDate = new Date(expMillis);
|
||||||
|
return Jwts.builder()
|
||||||
|
.setId(uuid)
|
||||||
|
.setSubject(subject)
|
||||||
|
.setIssuer("sg")
|
||||||
|
.setIssuedAt(now)
|
||||||
|
.signWith(signatureAlgorithm, secretKey)
|
||||||
|
.setExpiration(expDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SecretKey generalKey() {
|
||||||
|
byte[] encodeKey = Base64.getDecoder().decode(JwtUtil.JWT_KEY);
|
||||||
|
return new SecretKeySpec(encodeKey, 0, encodeKey.length, "HmacSHA256");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Claims parseJWT(String jwt) throws Exception {
|
||||||
|
SecretKey secretKey = generalKey();
|
||||||
|
return Jwts.parserBuilder()
|
||||||
|
.setSigningKey(secretKey)
|
||||||
|
.build()
|
||||||
|
.parseClaimsJws(jwt)
|
||||||
|
.getBody();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in new issue