diff --git a/pom.xml b/pom.xml index 549529a..6593ac1 100644 --- a/pom.xml +++ b/pom.xml @@ -32,10 +32,6 @@ org.springframework.boot spring-boot-starter-aop - - org.springframework.boot - spring-boot-starter-security - org.springframework.boot spring-boot-starter-data-jpa @@ -115,6 +111,14 @@ 1.2.61 + + + + cn.dev33 + sa-token-spring-boot-starter + 1.26.0 + + diff --git a/src/main/java/im/zhaojun/zfile/config/SaTokenConfigure.java b/src/main/java/im/zhaojun/zfile/config/SaTokenConfigure.java new file mode 100644 index 0000000..72cef57 --- /dev/null +++ b/src/main/java/im/zhaojun/zfile/config/SaTokenConfigure.java @@ -0,0 +1 @@ +package im.zhaojun.zfile.config; import cn.dev33.satoken.interceptor.SaRouteInterceptor; import cn.dev33.satoken.router.SaRouter; import cn.dev33.satoken.stp.StpUtil; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class SaTokenConfigure implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new SaRouteInterceptor((req, res, handler)->{ SaRouter.match("/admin/**", "/admin", StpUtil::checkLogin); })).addPathPatterns("/**"); } } \ No newline at end of file diff --git a/src/main/java/im/zhaojun/zfile/controller/admin/LoginController.java b/src/main/java/im/zhaojun/zfile/controller/admin/LoginController.java new file mode 100644 index 0000000..c864c91 --- /dev/null +++ b/src/main/java/im/zhaojun/zfile/controller/admin/LoginController.java @@ -0,0 +1 @@ +package im.zhaojun.zfile.controller.admin; import cn.dev33.satoken.stp.StpUtil; import cn.hutool.crypto.SecureUtil; import im.zhaojun.zfile.model.dto.SystemConfigDTO; import im.zhaojun.zfile.model.support.ResultBean; import im.zhaojun.zfile.service.SystemConfigService; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import java.util.Objects; @RestController public class LoginController { @Resource private SystemConfigService systemConfigService; @PostMapping("/login") public ResultBean doLogin(String username, String password) { SystemConfigDTO systemConfig = systemConfigService.getSystemConfig(); if (Objects.equals(username, systemConfig.getUsername()) && Objects.equals(SecureUtil.md5(password), systemConfig.getPassword())) { StpUtil.login("admin"); return ResultBean.success("登录成功"); } return ResultBean.error("登录失败"); } @GetMapping("/logout") public ResultBean logout() { StpUtil.logout(); return ResultBean.success("注销成功"); } } \ No newline at end of file diff --git a/src/main/java/im/zhaojun/zfile/exception/GlobleExceptionHandler.java b/src/main/java/im/zhaojun/zfile/exception/GlobleExceptionHandler.java index fbb3112..d6af2f0 100644 --- a/src/main/java/im/zhaojun/zfile/exception/GlobleExceptionHandler.java +++ b/src/main/java/im/zhaojun/zfile/exception/GlobleExceptionHandler.java @@ -1,5 +1,6 @@ package im.zhaojun.zfile.exception; +import cn.dev33.satoken.exception.NotLoginException; import im.zhaojun.zfile.model.support.ResultBean; import org.apache.catalina.connector.ClientAbortException; import org.slf4j.Logger; @@ -94,6 +95,16 @@ public class GlobleExceptionHandler { return ResultBean.error(ex.getMessage()); } + /** + * 登录异常拦截器 + */ + @ExceptionHandler(NotLoginException.class) + @ResponseBody + @ResponseStatus + public ResultBean handlerNotLoginException(NotLoginException e) { + return ResultBean.error("未登录"); + } + @ExceptionHandler @ResponseBody diff --git a/src/main/java/im/zhaojun/zfile/security/Md5PasswordEncoder.java b/src/main/java/im/zhaojun/zfile/security/Md5PasswordEncoder.java deleted file mode 100644 index 3b1fcf6..0000000 --- a/src/main/java/im/zhaojun/zfile/security/Md5PasswordEncoder.java +++ /dev/null @@ -1,20 +0,0 @@ -package im.zhaojun.zfile.security; - -import cn.hutool.crypto.SecureUtil; -import org.springframework.security.crypto.password.PasswordEncoder; - -/** - * @author zhaojun - */ -public class Md5PasswordEncoder implements PasswordEncoder { - - @Override - public String encode(CharSequence rawPassword) { - return SecureUtil.md5(rawPassword.toString()); - } - - @Override - public boolean matches(CharSequence rawPassword, String encodedPassword) { - return SecureUtil.md5(rawPassword.toString()).equals(encodedPassword); - } -} diff --git a/src/main/java/im/zhaojun/zfile/security/MySecurityConfig.java b/src/main/java/im/zhaojun/zfile/security/MySecurityConfig.java deleted file mode 100644 index 2723ac9..0000000 --- a/src/main/java/im/zhaojun/zfile/security/MySecurityConfig.java +++ /dev/null @@ -1,134 +0,0 @@ -package im.zhaojun.zfile.security; - -import com.fasterxml.jackson.databind.ObjectMapper; -import im.zhaojun.zfile.model.support.ResultBean; -import org.springframework.context.annotation.Bean; -import org.springframework.http.HttpMethod; -import org.springframework.security.authentication.BadCredentialsException; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -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.core.userdetails.UsernameNotFoundException; -import org.springframework.security.crypto.password.PasswordEncoder; -import org.springframework.security.web.firewall.HttpFirewall; -import org.springframework.security.web.firewall.StrictHttpFirewall; - -import javax.annotation.Resource; -import javax.servlet.http.HttpServletResponse; -import java.io.PrintWriter; - -/** - * 自定义 Security 配置类 - * - * @author zhaojun - */ -@EnableWebSecurity -public class MySecurityConfig extends WebSecurityConfigurerAdapter { - - @Resource - private ObjectMapper objectMapper; - - @Override - protected void configure(HttpSecurity http) throws Exception { - http - // .authenticationProvider(authenticationProvider()) - .exceptionHandling() - // 未登录时,进行 json 格式的提示. - .authenticationEntryPoint((request, response, authException) -> { - response.setContentType("application/json;charset=utf-8"); - response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); - PrintWriter out = response.getWriter(); - out.write(objectMapper.writeValueAsString(ResultBean.error("未登录"))); - out.flush(); - out.close(); - }) - .and() - .authorizeRequests() - .antMatchers("/").permitAll() - .antMatchers("/admin/**").authenticated() - .and() - .formLogin() // 使用自带的登录 - // 登录失败,返回json - .failureHandler((request, response, ex) -> { - response.setContentType("application/json;charset=utf-8"); - response.setStatus(HttpServletResponse.SC_FORBIDDEN); - PrintWriter out = response.getWriter(); - String msg; - if (ex instanceof UsernameNotFoundException || ex instanceof BadCredentialsException) { - msg = "用户名或密码错误"; - } else { - msg = "登录失败"; - } - out.write(objectMapper.writeValueAsString(ResultBean.error(msg))); - out.flush(); - out.close(); - }) - // 登录成功,返回json - .successHandler((request, response, authentication) -> { - response.setContentType("application/json;charset=utf-8"); - PrintWriter out = response.getWriter(); - out.write(objectMapper.writeValueAsString(ResultBean.success(authentication))); - out.flush(); - out.close(); - }) - .and() - .exceptionHandling() - // 没有权限,返回json - .accessDeniedHandler((request, response, ex) -> { - response.setContentType("application/json;charset=utf-8"); - response.setStatus(HttpServletResponse.SC_FORBIDDEN); - PrintWriter out = response.getWriter(); - out.write(objectMapper.writeValueAsString(ResultBean.error("权限不足"))); - out.flush(); - out.close(); - }) - .and() - .logout() - // 退出成功,返回 json - .logoutSuccessHandler((request, response, authentication) -> { - response.setContentType("application/json;charset=utf-8"); - PrintWriter out = response.getWriter(); - out.write(objectMapper.writeValueAsString(ResultBean.error("注销成功"))); - out.flush(); - out.close(); - }) - .and() - .logout().permitAll(); - - http.cors(); - http.csrf().disable(); - http.headers().frameOptions().sameOrigin(); - } - - @Bean - public HttpFirewall allowUrlEncodedSlashHttpFirewall() { - StrictHttpFirewall firewall = new StrictHttpFirewall(); - firewall.setAllowUrlEncodedPercent(true); - return firewall; - } - - @Override - public void configure(AuthenticationManagerBuilder web) throws Exception { - web.userDetailsService(myUserDetailsServiceImpl()).passwordEncoder(passwordEncoder()); - } - - @Bean - public MyUserDetailsServiceImpl myUserDetailsServiceImpl() { - return new MyUserDetailsServiceImpl(); - } - - @Override - public void configure(WebSecurity web) { - // 对于在 header 里面增加 token 等类似情况,放行所有 OPTIONS 请求。 - web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**"); - web.httpFirewall(allowUrlEncodedSlashHttpFirewall()); - } - - @Bean - public static PasswordEncoder passwordEncoder() { - return new Md5PasswordEncoder(); - } - -} \ No newline at end of file diff --git a/src/main/java/im/zhaojun/zfile/security/MyUserDetailsServiceImpl.java b/src/main/java/im/zhaojun/zfile/security/MyUserDetailsServiceImpl.java deleted file mode 100644 index b807368..0000000 --- a/src/main/java/im/zhaojun/zfile/security/MyUserDetailsServiceImpl.java +++ /dev/null @@ -1,34 +0,0 @@ -package im.zhaojun.zfile.security; - -import im.zhaojun.zfile.model.dto.SystemConfigDTO; -import im.zhaojun.zfile.service.SystemConfigService; -import org.springframework.security.core.userdetails.User; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.core.userdetails.UsernameNotFoundException; - -import javax.annotation.Resource; -import java.util.Collections; -import java.util.Objects; - -/** - * @author zhaojun - */ -public class MyUserDetailsServiceImpl implements UserDetailsService { - - @Resource - private SystemConfigService systemConfigService; - - /** - * 授权的时候是对角色授权,认证的时候应该基于资源,而不是角色,因为资源是不变的,而用户的角色是会变的 - */ - @Override - public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { - SystemConfigDTO systemConfig = systemConfigService.getSystemConfig(); - if (!Objects.equals(systemConfig.getUsername(), username)) { - throw new UsernameNotFoundException("用户名不存在"); - } - return new User(systemConfig.getUsername(), systemConfig.getPassword(), Collections.emptyList()); - } - -} \ No newline at end of file