Feat: add user interface complete

This commit is contained in:
xinsin 2023-04-22 13:37:26 +08:00
parent a429feb9a8
commit a97ae1747d
14 changed files with 222 additions and 85 deletions

View File

@ -115,6 +115,10 @@
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>

View File

@ -19,15 +19,6 @@ public class GlobalWebMvcConfiguration implements WebMvcConfigurer {
@Autowired
private AuthorizeInterceptor interceptor;
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowCredentials(true)
.allowedOriginPatterns("*")
.allowedMethods("*")
.allowedHeaders("*")
.exposedHeaders("*");
}
@Override
public void addInterceptors(InterceptorRegistry registry) {

View File

@ -12,6 +12,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import top.xinsin.util.R;
import java.util.Objects;
@Slf4j
@ControllerAdvice
public class InterceptResponseConfiguration implements ResponseBodyAdvice<Object> {
@ -24,7 +26,7 @@ public class InterceptResponseConfiguration implements ResponseBodyAdvice<Object
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
// 只有返回数据为自定义返回格式,才对数据进行处理
if (body instanceof R<?> r){
String controllerMethodName = returnType.getMethod().getName();
String controllerMethodName = Objects.requireNonNull(returnType.getMethod()).getName();
String controllerClassName = returnType.getDeclaringClass().getSimpleName();
String controllerClassURlPath = returnType.getDeclaringClass().getAnnotation(RequestMapping.class).value()[0];
RequestMapping annotation = returnType.getMethod().getAnnotation(RequestMapping.class);

View File

@ -13,6 +13,7 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
@ -36,7 +37,7 @@ public class SecurityConfiguration {
@Autowired
DataSource dataSource;
@Bean
public SecurityFilterChain filterChain(HttpSecurity httpSecurity, PersistentTokenRepository persistentTokenRepository) throws Exception {
public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
return httpSecurity
.authorizeHttpRequests()
.requestMatchers("/api/auth/**")
@ -53,11 +54,6 @@ public class SecurityConfiguration {
.logoutUrl("/api/auth/logout")
.logoutSuccessHandler(this::onsuccessLoginHandler)
.and()
.rememberMe()
.rememberMeParameter("remember")
.tokenRepository(persistentTokenRepository)
.tokenValiditySeconds(60 * 60 * 12)
.and()
.csrf()
.disable()
.cors()
@ -69,13 +65,6 @@ public class SecurityConfiguration {
.build();
}
@Bean
public PersistentTokenRepository tokenRepository(){
JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
jdbcTokenRepository.setDataSource(dataSource);
jdbcTokenRepository.setCreateTableOnStartup(false);
return jdbcTokenRepository;
}
@Bean
public AuthenticationManager authenticationManager(HttpSecurity security) throws Exception {
return security
.getSharedObject(AuthenticationManagerBuilder.class)
@ -100,13 +89,31 @@ public class SecurityConfiguration {
}
private void onsuccessLoginHandler(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException {
httpServletResponse.setCharacterEncoding("utf-8");
if(httpServletRequest.getRequestURI().endsWith("/login"))
httpServletResponse.getWriter().write(JSONObject.toJSONString(R.success("登陆成功")));
else if(httpServletRequest.getRequestURI().endsWith("/logout"))
httpServletResponse.setHeader("Content-Type","application/json; charset=UTF-8");
if(httpServletRequest.getRequestURI().endsWith("/login")) {
JSONObject jsonObject = new JSONObject();
authentication.getAuthorities().forEach(e -> {
String authority = e.getAuthority();
if (authority.startsWith("ROLE_id=")){
jsonObject.fluentPut("id",authority.replace("ROLE_id=", ""));
}
if (authority.startsWith("ROLE_role=")){
jsonObject.fluentPut("role",authority.replace("ROLE_role=",""));
}
});
jsonObject
.fluentPut("message","登陆成功");
httpServletResponse.setStatus(HttpCodes.HTTP_CODES200.getCode());
httpServletResponse.getWriter().write(JSONObject.toJSONString(R.success(jsonObject)));
} else if(httpServletRequest.getRequestURI().endsWith("/logout")) {
httpServletResponse.setStatus(HttpCodes.HTTP_CODES200.getCode());
httpServletResponse.getWriter().write(JSONObject.toJSONString(R.success("退出登录成功")));
}
}
private void onFailureLoginHandler(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse,AuthenticationException authentication) throws IOException {
httpServletResponse.setCharacterEncoding("utf-8");
httpServletResponse.setHeader("Content-Type","application/json; charset=UTF-8");
httpServletResponse.setStatus(HttpCodes.HTTP_CODES555.getCode());
httpServletResponse.getWriter().write(JSONObject.toJSONString(R.failed(HttpCodes.ACCESS_DENIED,"登录时出现了错误")));
}
}

View File

@ -1,11 +1,12 @@
package top.xinsin.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import com.alibaba.fastjson2.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import top.xinsin.pojo.Account;
import top.xinsin.service.AccountService;
import top.xinsin.util.HttpCodes;
import top.xinsin.util.R;
@ -20,10 +21,27 @@ import top.xinsin.util.R;
@RestController
@RequestMapping("/account")
public class AccountController {
@Autowired
private AccountService accountService;
@RequestMapping(path = "/get",method = RequestMethod.GET)
public R<String> get(){
return R.failed(HttpCodes.HTTP_CODES500,"234567890");
@RequestMapping(path = "/changeAccount",method = RequestMethod.POST)
public R<String> changeAccount(@RequestBody Account account){
return accountService.changeAccount(account);
}
@RequestMapping(path = "/changeStatus",method = RequestMethod.GET)
public R<String> changeStatus(@RequestParam("userId")Integer userId,@RequestParam("status")Boolean status){
return accountService.changeStatus(userId,status);
}
@RequestMapping(path = "/changePassword",method = RequestMethod.GET)
public R<String> changePassword(@RequestParam("userId")Integer userId,@RequestParam("oldPassword")String oldPassword,@RequestParam("newPassword") String newPassword){
return accountService.changePassword(userId,oldPassword,newPassword);
}
@RequestMapping(path = "/delUser",method = RequestMethod.GET)
public R<String> delUser(@RequestParam("id")Integer id){
return accountService.delUser(id);
}
@RequestMapping(path = "/getUser",method = RequestMethod.GET)
public R<JSONObject> getUser(@RequestParam("page")Integer page,@RequestParam("num")Integer num){
return accountService.getUser(page,num);
}
}

View File

@ -0,0 +1,37 @@
package top.xinsin.controller;
import jakarta.validation.constraints.Pattern;
import org.hibernate.validator.constraints.Length;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import top.xinsin.pojo.Account;
import top.xinsin.service.AccountService;
import top.xinsin.util.R;
import static top.xinsin.util.StringConstant.*;
@Validated
@RestController
@RequestMapping("/api/auth")
public class AuthorizeController {
@Autowired
private AccountService accountService;
@RequestMapping(path = "/register",method = RequestMethod.POST)
public R<String> register(@Pattern(regexp = USERNAME_REGEX) @Length(min = 3,max = 10) @RequestParam("username") String username,
@Pattern(regexp = REL_NAME_REGEX) @RequestParam("relName") String relName,
@Pattern(regexp = EMAIL_REGEX) @RequestParam("email") String email,
@RequestParam("password") String password,
@Pattern(regexp = ID_REGEX) @RequestParam("roleId") Integer roleId){
Account account = new Account();
account.setUsername(username);
account.setPassword(password);
account.setRelName(relName);
account.setEmail(email);
account.setRoleId(roleId);
return accountService.register(account);
}
}

View File

@ -27,7 +27,8 @@ public class AuthorizeInterceptor implements HandlerInterceptor {
Account account = accountMapper.selectOne(new LambdaQueryWrapper<Account>()
.eq(Account::getUsername,username)
.or()
.eq(Account::getEmail,username));
.eq(Account::getEmail,username)
.eq(Account::getStatus,true));
request.getSession().setAttribute("account", account);
return true;
}

View File

@ -1,10 +1,12 @@
package top.xinsin.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
@ -22,29 +24,39 @@ import org.springframework.format.annotation.DateTimeFormat;
@TableName("account")
public class Account implements Serializable {
private static final long serialVersionUID = 1L;
@TableId("id")
private Integer id;
@TableField("username")
private String username;
@TableField("email")
private String email;
@TableField("rel_name")
private String relName;
@TableField("password")
private String password;
@TableField("status")
private Boolean status;
@TableField("role_id")
private Integer roleId;
@TableField("create_time")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime createTime;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@TableField("update_time")
private LocalDateTime updateTime;
@TableField("del")
private Boolean del;
private static final long serialVersionUID = 1L;
@TableId(value = "id",type = IdType.AUTO)
private Integer id;
@TableField("username")
private String username;
@TableField("email")
private String email;
@TableField("rel_name")
private String relName;
@TableField("password")
private String password;
@TableField("status")
private Boolean status;
@TableField("role_id")
private Integer roleId;
@TableField("create_time")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@TableField("update_time")
private Date updateTime;
@TableField("del")
private Boolean del;
}

View File

@ -1,6 +1,8 @@
package top.xinsin.service;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
@ -11,6 +13,13 @@ import org.springframework.stereotype.Service;
import top.xinsin.mapper.AccountMapper;
import top.xinsin.pojo.Account;
import com.baomidou.mybatisplus.extension.service.IService;
import top.xinsin.util.HttpCodes;
import top.xinsin.util.R;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;
/**
* <p>
@ -35,12 +44,71 @@ public class AccountService implements UserDetailsService {
Account account = accountMapper.selectOne(new LambdaQueryWrapper<Account>()
.eq(Account::getUsername,username)
.or()
.eq(Account::getEmail,username));
.eq(Account::getEmail,username)
.eq(Account::getStatus,true));
if(account == null) throw new UsernameNotFoundException("用户名或密码错误");
return User
.withUsername(account.getUsername())
.password(account.getPassword())
.roles(String.valueOf(account.getRoleId()))
.roles("role=" + account.getRoleId(),"id=" + account.getId())
.build();
}
public R<String> register(Account account) {
account.setCreateTime(new Date());
account.setStatus(true);
account.setPassword(encoder.encode(account.getPassword()));
int insert = accountMapper.insert(account);
return insert == 1 ? R.success("注册成功") : R.failed(HttpCodes.HTTP_CODES555,"注册失败,您的用户名或者邮箱已经被注册过了");
}
public R<String> changeAccount(Account account) {
if (account.getPassword() != null){
account.setPassword(encoder.encode(account.getPassword()));
}
int update = accountMapper.updateById(account);
return update == 1 ? R.success("修改用户信息成功") : R.failed(HttpCodes.HTTP_CODES555,"修改用户信息失败,请联系服务器管理员");
}
public R<String> changeStatus(Integer userId, Boolean status) {
Account account = new Account();
account.setId(userId);
account.setStatus(status);
int i = accountMapper.updateById(account);
if (i == 1){
if (status){
return R.success("启用该用户成功");
}else{
return R.success("禁用该用户成功");
}
}else{
return R.failed(HttpCodes.HTTP_CODES555,"修改用户状态失败");
}
}
public R<String> changePassword(Integer userId, String oldPassword, String newPassword) {
Account account = new Account();
account.setPassword(encoder.encode(newPassword));
LambdaQueryWrapper<Account> accountLambdaQueryWrapper = new LambdaQueryWrapper<>();
accountLambdaQueryWrapper
.eq(Account::getId,userId)
.eq(Account::getPassword,encoder.encode(oldPassword));
int update = accountMapper.update(account, accountLambdaQueryWrapper);
return update == 1 ? R.success("修改密码成功") : R.failed(HttpCodes.HTTP_CODES555,"修改密码失败,请联系服务器管理员");
}
public R<JSONObject> getUser(Integer page, Integer num) {
Page<Account> accountPage = new Page<>(page,num);
Page<Account> accountPage1 = accountMapper.selectPage(accountPage, null);
JSONObject jsonObject = new JSONObject();
List<Account> collect = accountPage1.getRecords().stream().peek(e -> e.setPassword(null)).toList();
jsonObject
.fluentPut("info",collect)
.fluentPut("total",accountPage1.getTotal());
return R.success(jsonObject);
}
public R<String> delUser(Integer id) {
int delete = accountMapper.deleteById(id);
return delete == 1 ? R.success("删除用户成功") : R.failed(HttpCodes.HTTP_CODES555,"删除用户失败,请联系服务器管理员");
}
}

View File

@ -22,6 +22,11 @@ public enum HttpCodes {
* 数据错误
*/
HTTP_CODES401(401,"这是一个坏的请求,请重新写入参数"),
/**
* 555
* 数据更新失败
*/
HTTP_CODES555(555,"数据更新失败"),
/**
* 501
* 账号密码错误

View File

@ -1,20 +0,0 @@
package top.xinsin.util;
import com.alibaba.fastjson2.JSON;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.SneakyThrows;
/**
* 将数据渲染到前端
*/
public class ServletUtils {
@SneakyThrows
public static void render(HttpServletRequest request, HttpServletResponse response,R<?> o){
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Headers", "token, Accept, Origin, X-Requested-With, Content-Type, Last-Modified");
response.setHeader("Content-type", "application/json;charset=UTF-8");
response.getWriter().print(JSON.toJSONString(o));
}
}

View File

@ -0,0 +1,8 @@
package top.xinsin.util;
public class StringConstant {
public static final String REL_NAME_REGEX = "[一-龥]{2,4}";
public static final String EMAIL_REGEX = "\\w[-\\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\\.)+[A-Za-z]{2,14}";
public static final String USERNAME_REGEX = "[A-Za-z0-9_\\-一-龥]+";
public static final String ID_REGEX = "[0-9]*";
}

View File

@ -24,6 +24,12 @@ spring:
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
data:
redis:
database: 1
host: wzpmc.cn
port: 6379
password: MyCraftAdmin123
mvc:
static-path-pattern: /static/**
security:

View File

@ -14,9 +14,7 @@ import java.util.function.Consumer;
public class CodeGenerator {
public static void main(String[] args) {
List<String> tables = new ArrayList<>();
tables.add("account");
tables.add("roles");
tables.add("permissions");
tables.add("order");
FastAutoGenerator.create("jdbc:mysql://wzpmc.cn:3306/commerce_system?serverTimezone=UTC-8","commerce_system","Jix656dzD6St4YCn")
.globalConfig(builder -> {