parent
d923ecf1f5
commit
89a243d86d
@ -1,5 +1,52 @@
|
||||
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