♻️ 修改 Spring Security 为 Sa-Token 框架.

This commit is contained in:
赵俊
2021-09-19 09:57:09 +08:00
parent d15d1203b7
commit 10c465d159
7 changed files with 21 additions and 192 deletions

View File

@@ -0,0 +1 @@
package im.zhaojun.zfile.config;

View File

@@ -0,0 +1 @@
package im.zhaojun.zfile.controller.admin;

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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();
}
}

View File

@@ -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());
}
}