diff --git a/pom.xml b/pom.xml index 0638a16..d3551c6 100644 --- a/pom.xml +++ b/pom.xml @@ -115,6 +115,10 @@ org.springframework.session spring-session-data-redis + + org.springframework.boot + spring-boot-starter-validation + org.freemarker freemarker diff --git a/src/main/java/top/xinsin/config/GlobalWebMvcConfiguration.java b/src/main/java/top/xinsin/config/GlobalWebMvcConfiguration.java index 60a13fc..2ab61fc 100644 --- a/src/main/java/top/xinsin/config/GlobalWebMvcConfiguration.java +++ b/src/main/java/top/xinsin/config/GlobalWebMvcConfiguration.java @@ -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) { diff --git a/src/main/java/top/xinsin/config/InterceptResponseConfiguration.java b/src/main/java/top/xinsin/config/InterceptResponseConfiguration.java index 3e0bcdb..7733df6 100644 --- a/src/main/java/top/xinsin/config/InterceptResponseConfiguration.java +++ b/src/main/java/top/xinsin/config/InterceptResponseConfiguration.java @@ -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 { @@ -24,7 +26,7 @@ public class InterceptResponseConfiguration implements ResponseBodyAdvice> 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); diff --git a/src/main/java/top/xinsin/config/SecurityConfiguration.java b/src/main/java/top/xinsin/config/SecurityConfiguration.java index 6562516..3e88c9f 100644 --- a/src/main/java/top/xinsin/config/SecurityConfiguration.java +++ b/src/main/java/top/xinsin/config/SecurityConfiguration.java @@ -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,"登录时出现了错误"))); } } diff --git a/src/main/java/top/xinsin/controller/AccountController.java b/src/main/java/top/xinsin/controller/AccountController.java index b118cb9..9edb757 100644 --- a/src/main/java/top/xinsin/controller/AccountController.java +++ b/src/main/java/top/xinsin/controller/AccountController.java @@ -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 get(){ - return R.failed(HttpCodes.HTTP_CODES500,"234567890"); + @RequestMapping(path = "/changeAccount",method = RequestMethod.POST) + public R changeAccount(@RequestBody Account account){ + return accountService.changeAccount(account); + } + @RequestMapping(path = "/changeStatus",method = RequestMethod.GET) + public R changeStatus(@RequestParam("userId")Integer userId,@RequestParam("status")Boolean status){ + return accountService.changeStatus(userId,status); + } + @RequestMapping(path = "/changePassword",method = RequestMethod.GET) + public R 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 delUser(@RequestParam("id")Integer id){ + return accountService.delUser(id); + } + @RequestMapping(path = "/getUser",method = RequestMethod.GET) + public R getUser(@RequestParam("page")Integer page,@RequestParam("num")Integer num){ + return accountService.getUser(page,num); } - } diff --git a/src/main/java/top/xinsin/controller/AuthorizeController.java b/src/main/java/top/xinsin/controller/AuthorizeController.java new file mode 100644 index 0000000..32b0b5a --- /dev/null +++ b/src/main/java/top/xinsin/controller/AuthorizeController.java @@ -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 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); + } +} diff --git a/src/main/java/top/xinsin/interceptor/AuthorizeInterceptor.java b/src/main/java/top/xinsin/interceptor/AuthorizeInterceptor.java index 8a7fa89..21d5692 100644 --- a/src/main/java/top/xinsin/interceptor/AuthorizeInterceptor.java +++ b/src/main/java/top/xinsin/interceptor/AuthorizeInterceptor.java @@ -27,7 +27,8 @@ public class AuthorizeInterceptor implements HandlerInterceptor { Account account = accountMapper.selectOne(new LambdaQueryWrapper() .eq(Account::getUsername,username) .or() - .eq(Account::getEmail,username)); + .eq(Account::getEmail,username) + .eq(Account::getStatus,true)); request.getSession().setAttribute("account", account); return true; } diff --git a/src/main/java/top/xinsin/pojo/Account.java b/src/main/java/top/xinsin/pojo/Account.java index d781070..118f709 100644 --- a/src/main/java/top/xinsin/pojo/Account.java +++ b/src/main/java/top/xinsin/pojo/Account.java @@ -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; } \ No newline at end of file diff --git a/src/main/java/top/xinsin/service/AccountService.java b/src/main/java/top/xinsin/service/AccountService.java index 7e88dd2..4724937 100644 --- a/src/main/java/top/xinsin/service/AccountService.java +++ b/src/main/java/top/xinsin/service/AccountService.java @@ -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; /** *

@@ -35,12 +44,71 @@ public class AccountService implements UserDetailsService { Account account = accountMapper.selectOne(new LambdaQueryWrapper() .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 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 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 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 changePassword(Integer userId, String oldPassword, String newPassword) { + Account account = new Account(); + account.setPassword(encoder.encode(newPassword)); + LambdaQueryWrapper 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 getUser(Integer page, Integer num) { + Page accountPage = new Page<>(page,num); + Page accountPage1 = accountMapper.selectPage(accountPage, null); + JSONObject jsonObject = new JSONObject(); + List collect = accountPage1.getRecords().stream().peek(e -> e.setPassword(null)).toList(); + jsonObject + .fluentPut("info",collect) + .fluentPut("total",accountPage1.getTotal()); + return R.success(jsonObject); + } + + public R delUser(Integer id) { + int delete = accountMapper.deleteById(id); + return delete == 1 ? R.success("删除用户成功") : R.failed(HttpCodes.HTTP_CODES555,"删除用户失败,请联系服务器管理员"); + } } diff --git a/src/main/java/top/xinsin/util/HttpCodes.java b/src/main/java/top/xinsin/util/HttpCodes.java index b027c05..18dd04e 100644 --- a/src/main/java/top/xinsin/util/HttpCodes.java +++ b/src/main/java/top/xinsin/util/HttpCodes.java @@ -22,6 +22,11 @@ public enum HttpCodes { * 数据错误 */ HTTP_CODES401(401,"这是一个坏的请求,请重新写入参数"), + /** + * 555 + * 数据更新失败 + */ + HTTP_CODES555(555,"数据更新失败"), /** * 501 * 账号密码错误 diff --git a/src/main/java/top/xinsin/util/ServletUtils.java b/src/main/java/top/xinsin/util/ServletUtils.java deleted file mode 100644 index 717e695..0000000 --- a/src/main/java/top/xinsin/util/ServletUtils.java +++ /dev/null @@ -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)); - } -} diff --git a/src/main/java/top/xinsin/util/StringConstant.java b/src/main/java/top/xinsin/util/StringConstant.java new file mode 100644 index 0000000..5d8b0dc --- /dev/null +++ b/src/main/java/top/xinsin/util/StringConstant.java @@ -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]*"; +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index d592f3d..84f06c1 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -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: diff --git a/src/test/java/top/xinsin/CodeGenerator.java b/src/test/java/top/xinsin/CodeGenerator.java index a078d45..03f7d94 100644 --- a/src/test/java/top/xinsin/CodeGenerator.java +++ b/src/test/java/top/xinsin/CodeGenerator.java @@ -14,9 +14,7 @@ import java.util.function.Consumer; public class CodeGenerator { public static void main(String[] args) { List 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 -> {