需要配置Web应用安全适配器
import com.sikiedu.RESTfulMaven.handler.LoginFailureHandler;
import com.sikiedu.RESTfulMaven.handler.LoginSuccessHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
//web应用安全适配器
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//告诉SpringSecurity我们密码是用什么加密的
@Bean
public BCryptPasswordEncoder passwordEncoder()
{
return new BCryptPasswordEncoder();
}
@Autowired
private LoginSuccessHandler loginSuccessHandler;
@Autowired
private LoginFailureHandler loginFailureHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
//表单登陆(身份认证)
http.formLogin()
//自定义登陆页面
.loginPage("/require")
//如果URL为loginPage,则用SpringSecurity中自带的过滤器去处理请求
.loginProcessingUrl("/loginPage")
//登陆成功后的处理
.successHandler(loginSuccessHandler)
//登陆失败后的处理
.failureHandler(loginFailureHandler)
.and()
//请求授权
.authorizeRequests()
//在访问我们的loginURL,我们是不需要身份认证,可以立即访问
.antMatchers("/login.html","/require").permitAll()
//所有请求(/user)
.anyRequest()
//都需要我们身份认证
.authenticated()
//关闭跨站请求伪造的防护
.and().csrf().disable();
}
}
Controller
import org.springframework.http.HttpStatus;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
import org.springframework.security.web.savedrequest.RequestCache;
import org.springframework.security.web.savedrequest.SavedRequest;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.Period;
@RestController
public class SecurityController {
//拿到引发跳转之前的请求
private RequestCache requestCache=new HttpSessionRequestCache();
//可以用来做重定向
private RedirectStrategy redirectStrategy=new DefaultRedirectStrategy();
@RequestMapping("/require")
//返回的状态码401
@ResponseStatus(code = HttpStatus.UNAUTHORIZED)
public String require(HttpServletRequest request, HttpServletResponse response) throws Exception {
//判断之前的请求是否以html结尾
SavedRequest savedRequest = requestCache.getRequest(request, response);
if(savedRequest!=null)
{
//url就是引发跳转之前的请求
String url = savedRequest.getRedirectUrl();
//判断之前的请求是否以html结尾
if(StringUtils.endsWithIgnoreCase(url,".html"))
{
//如果是,重定向到登陆页面
redirectStrategy.sendRedirect(request,response,"/login.html");
}
}
//如果不是,我们就让他身份认证
return new String("需要身份认证");
}
}
登陆失败成功的页面设置
成功
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
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
public class LoginSuccessHandler implements AuthenticationSuccessHandler {
//将我们的authentication转换为json所需要的类
@Autowired
private ObjectMapper objectMapper;
@Override
//登陆成功之后会调用的函数
//封装了我们的认证信息(发起的认证请求(ip,session) 认证成功之后的用户信息)
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
Authentication authentication) throws IOException, ServletException {
System.out.println("登陆成功");
httpServletResponse.setContentType("application/json;charset=UTF-8");
//将我们quthentication转为json通过response对象以application/json写到页面
httpServletResponse.getWriter().write(objectMapper.writeValueAsString(authentication));
}
}
失败(状态码为500)
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.AuthenticationException;
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.beans.Expression;
import java.io.IOException;
@Component
public class LoginFailureHandler implements AuthenticationFailureHandler {
@Autowired
private ObjectMapper objectMapper;
@Override
//登陆失败之后调用的方法
public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
//登陆不成功产生的错误
AuthenticationException e) throws IOException, ServletException {
System.out.println("登陆失败");
//设置返回的状态码(500)
httpServletResponse.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
httpServletResponse.setContentType("application/json:charset=UTF-8");
httpServletResponse.getWriter().write(objectMapper.writeValueAsString(e));
}
}