1、创建Http约束类
public interface HttpStatus {
int SUCCESS = 0;
int NOT_LOGIN = 1001;
int NOT_REGISTER = 1002;
int PASSWORD_ERROR = 1003;
int FORBIDDEN = 1004;
int EXCEPTION = 1005;
int AUTH_FAIL = 1006;
String SUCCESS_MSG = "success";
String NOT_LOGIN_MSG = "用户未登录";
String NOT_REGISTER_MSG = "用户未注册";
String PASSWORD_ERROR_MSG = "用户密码错误";
String FORBIDDEN_MSG = "用户无权访问";
String EXCEPTION_MSG = "系统异常";
String AUTH_FAIL_MSG = "登录验证失败";
}
2、创建统一返回对象
import com.alibaba.fastjson.JSONObject;
public class AjaxResult extends JSONObject {
public static AjaxResult success() {
return success(HttpStatus.SUCCESS_MSG, null);
}
public static AjaxResult success(String msg) {
return success(msg, null);
}
public static AjaxResult success(Object data) {
return success(HttpStatus.SUCCESS_MSG, data);
}
public static AjaxResult success(String msg, Object data) {
return new AjaxResult(HttpStatus.SUCCESS, msg, data);
}
public static AjaxResult error(int code, String msg) {
return new AjaxResult(code, msg, null);
}
public static AjaxResult error(int code, String msg, Object data) {
return new AjaxResult(code, msg, data);
}
private AjaxResult(int code, String msg, Object data) {
super.put("code", code);
super.put("msg", msg);
if (data != null) {
super.put("data", data);
}
}
}
3、自定义拒绝访问处理逻辑
import org.example.common.AjaxResult;
import org.example.common.HttpStatus;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 自定义拒绝访问处理逻辑
*/
@Component("accessDeniedHandler")
public class UserAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
httpServletResponse.setContentType("text/json;charset=utf-8");
httpServletResponse.getWriter().write(AjaxResult.error(HttpStatus.FORBIDDEN, HttpStatus.FORBIDDEN_MSG).toJSONString());
}
}
4、自定义未登录的处理逻辑
import org.example.common.AjaxResult;
import org.example.common.HttpStatus;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 自定义未登录的处理逻辑
*/
@Component("authenticationEntryPoint")
public class UserAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
httpServletResponse.setContentType("text/json;charset=utf-8");
httpServletResponse.getWriter().write(AjaxResult.error(HttpStatus.NOT_LOGIN, HttpStatus.NOT_LOGIN_MSG).toJSONString());
}
}
5、自定义登录失败处理逻辑
import org.example.common.AjaxResult;
import org.example.common.HttpStatus;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 自定义登录失败处理逻辑
*/
@Component("authenticationFailureHandler")
public class UserAuthenticationFailureHandler implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
AjaxResult result;
if (e instanceof UsernameNotFoundException) {
result = AjaxResult.error(HttpStatus.NOT_REGISTER, HttpStatus.NOT_REGISTER_MSG);
} else if (e instanceof BadCredentialsException) {
result = AjaxResult.error(HttpStatus.PASSWORD_ERROR, HttpStatus.PASSWORD_ERROR_MSG);
} else {
result = AjaxResult.error(HttpStatus.AUTH_FAIL, HttpStatus.AUTH_FAIL_MSG, e.getMessage());
}
httpServletResponse.setContentType("text/json;charset=utf-8");
httpServletResponse.getWriter().write(result.toJSONString());
}
}
6、自定义登录成功处理逻辑
import org.example.common.AjaxResult;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 自定义登录成功处理逻辑
*/
@Component("authenticationSuccessHandler")
public class UserAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
//设置响应头
httpServletResponse.setContentType("text/json;charset=utf-8");
httpServletResponse.getWriter().write(AjaxResult.success().toJSONString());
}
}
7、自定义登出成功处理逻辑
import org.example.common.AjaxResult;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 自定义登出成功处理逻辑
*/
@Component("logoutSuccessHandler")
public class UserLogoutSuccessHandler implements LogoutSuccessHandler {
@Override
public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
httpServletResponse.setContentType("text/json;charset=utf-8");
httpServletResponse.getWriter().write(AjaxResult.success().toJSONString());
}
}
8、配置UserWebSecurityConfigurerAdapter类
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class UserWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
//注入自定义登录成功处理类
@Autowired
private UserAuthenticationSuccessHandler authenticationSuccessHandler;
//注入自定义失败处理类
@Autowired
private UserAuthenticationFailureHandler authenticationFailureHandler;
//注入自定义未登录处理类
@Autowired
private UserAuthenticationEntryPoint authenticationEntryPoint;
//无权访问
@Autowired
private UserAccessDeniedHandler accessDeniedHandler;
//自定义认证逻辑处理
@Autowired
private UserAuthenticationProvider authenticationProvider;
//自定义登出成功逻辑处理
@Autowired
private UserLogoutSuccessHandler logoutSuccessHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
//禁用csrf
.csrf()
.disable()
//用户登录
.formLogin()
.loginPage("/login.html")
.loginProcessingUrl("/login")//自定义登录请求路径
.successHandler(authenticationSuccessHandler)//登录成功时的处理
.failureHandler(authenticationFailureHandler)//登录失败时的处理
//用户登出
.and()
.logout()
.logoutSuccessHandler(logoutSuccessHandler)//登出成功时的处理
//异常处理
.and()
.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler)//权限不足时的处理
.authenticationEntryPoint(authenticationEntryPoint)//未登录时的处理
//请求过滤
.and()
.authorizeRequests()
.antMatchers("/login.html", "/login").anonymous()//登录页与登录请求,只允许匿名访问
.anyRequest().authenticated();//除此之外,其他请求均需要登录后才可以访问
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider);
}
}
9、重写测试接口
@PreAuthorize
可用于标识授权信息,具体使用将在下一章说明。
1)@PreAuthorize("hasAuthority('sys:test:test1')")
表示用户需要拥有权限标识sys:test:test1
才可以访问
2)@PreAuthorize("hasRole('admin')")
表示用户需要拥有角色标识admin
才可以访问
import org.example.common.AjaxResult;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping
public class TestController {
@GetMapping("test")
public AjaxResult test() {
return AjaxResult.success("test success");
}
@PreAuthorize("hasAuthority('sys:test:test1')")
@GetMapping("test1")
public AjaxResult test1() {
return AjaxResult.success("test1 success:hasAuthority('sys:test:test1')");
}
@PreAuthorize("hasRole('admin')")
@GetMapping("test2")
public AjaxResult test2() {
return AjaxResult.success("test2 success:hasRole('admin')");
}
}
10、启动项目并测试接口
测试1:访问http://localhost:8080/login.html,输入账号密码:user4/111111,登录成功后,成功返回JSON对象
测试2:访问http://localhost:8080/login.html,输入账号密码:user1/222222,登录成功后,成功返回JSON对象
测试3:访问http://localhost:8080/login.html,输入账号密码:user1/111111,登录成功后,成功返回JSON对象
测试4:访问http://localhost:8080/test,成功返回JSON对象
测试5:访问http://localhost:8080/test1,成功返回JSON对象
测试6:访问http://localhost:8080/test2,成功返回JSON对象
测试7:访问http://localhost:8080/logout,成功返回JSON对象