配置类
package com.imooc.security.browser; import com.imooc.security.core.properties.SecurityProperties; 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.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.scrypt.SCryptPasswordEncoder; import org.springframework.security.web.authentication.AuthenticationFailureHandler; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; @Configuration public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private AuthenticationSuccessHandler imoocAuthenticationSuccessHandler; @Autowired private AuthenticationFailureHandler imoocAuthenctiationFailureHandler; @Bean public PasswordEncoder passwordEncoder() { return new SCryptPasswordEncoder(); } @Autowired private SecurityProperties securityProperties; @Override public void configure(HttpSecurity http) throws Exception { // 添加一个图片验证filter, 在那个Filter之前执行 http // .httpBasic() // 默认方式 .formLogin() // 设置认证的登录方式 表单方式 .loginPage("/authentication/require") // 自定义登录页面 .loginProcessingUrl("/authentication/form") // 自定义表单url, 默认是login .successHandler(imoocAuthenticationSuccessHandler) // 不适用默认的认证成功处理器 .failureHandler(imoocAuthenctiationFailureHandler) // 登录失败处理器 // .failureForwardUrl("/authentication/require") // .failureUrl("/authentication/require") .and() .authorizeRequests() // 需要授权 // 当匹配到这个页面时,不需要授权 .antMatchers("/authentication/require", securityProperties.getBrowser().getLoginPage(), "/code/image").permitAll() .anyRequest() // 所有请求 .authenticated() .and() // 关闭csrf .csrf() .disable(); } }
登录请求路由类
package com.imooc.security.browser; import java.io.IOException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; 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.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import com.imooc.security.browser.support.SimpleResponse; import com.imooc.security.core.properties.SecurityProperties; @RestController public class BrowserSecurityController { private Logger logger = LoggerFactory.getLogger(getClass()); // 请求的缓存类 private RequestCache requestCache = new HttpSessionRequestCache(); // spring 提供的跳转类 private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); @Autowired private SecurityProperties securityProperties; /** * 当需要身份认证时,跳转到这里 * * @param request * @param response * @return * @throws IOException */ @RequestMapping("/authentication/require") @ResponseStatus(code = HttpStatus.UNAUTHORIZED) public SimpleResponse requireAuthentication(HttpServletRequest request, HttpServletResponse response) throws IOException { // 之前缓存的请求 SavedRequest savedRequest = requestCache.getRequest(request, response); if (savedRequest != null) { String targetUrl = savedRequest.getRedirectUrl(); // 引发跳转的请求url logger.info("引发跳转的请求是:" + targetUrl); if (StringUtils.endsWithIgnoreCase(targetUrl, ".html")) { // 如果url包含html跳转 redirectStrategy.sendRedirect(request, response, securityProperties.getBrowser().getLoginPage()); } } return new SimpleResponse("访问的服务需要身份认证,请引导用户到登录页"); } }
权限加载验证类
package com.imooc.security.browser; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.authority.AuthorityUtils; 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 org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Component; @Component public class MyUserDetailsService implements UserDetailsService { // 模拟密码加密 @Autowired private PasswordEncoder passwordEncoder; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { // 模拟用户数据库查询密码 String enPass = passwordEncoder.encode("123456"); return new User(username, enPass, true,true,true,true, AuthorityUtils.commaSeparatedStringToAuthorityList("admin")); } }
失败处理器
package com.imooc.security.browser.authentication; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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.security.web.authentication.SimpleUrlAuthenticationFailureHandler; import org.springframework.stereotype.Component; import com.fasterxml.jackson.databind.ObjectMapper; import com.imooc.security.browser.support.SimpleResponse; import com.imooc.security.core.properties.LoginResponseType; import com.imooc.security.core.properties.SecurityProperties; @Component("imoocAuthenctiationFailureHandler") //public class ImoocAuthenctiationFailureHandler implements AuthenticationFailureHandler { public class ImoocAuthenctiationFailureHandler extends SimpleUrlAuthenticationFailureHandler { private Logger logger = LoggerFactory.getLogger(getClass()); @Autowired private ObjectMapper objectMapper; @Autowired private SecurityProperties securityProperties; /*@Override public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { logger.info("登录失败"); response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value()); response.setContentType("application/json;charset=UTF-8"); response.getWriter().write(objectMapper.writeValueAsString(new SimpleResponse(exception.getMessage()))); } */ @Override public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { logger.info("登录失败"); // 返回json if (LoginResponseType.JSON.equals(securityProperties.getBrowser().getLoginType())) { response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value()); response.setContentType("application/json;charset=UTF-8"); response.getWriter().write(objectMapper.writeValueAsString(new SimpleResponse(exception.getMessage()))); }else{ // 调用默认处理方式 跳转页面 super.onAuthenticationFailure(request, response, exception); } } }
成功处理器
package com.imooc.security.browser.authentication; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; import org.springframework.stereotype.Component; import com.fasterxml.jackson.databind.ObjectMapper; import com.imooc.security.core.properties.LoginResponseType; import com.imooc.security.core.properties.SecurityProperties; @Component("imoocAuthenticationSuccessHandler") //public class ImoocAuthenticationSuccessHandler implements AuthenticationSuccessHandler { // json方式处理 public class ImoocAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler { // 自定义返回方式 private Logger logger = LoggerFactory.getLogger(getClass()); @Autowired private ObjectMapper objectMapper; @Autowired private SecurityProperties securityProperties; /** * @param request * @param response * @param authentication 存放认证信息 * @throws IOException * @throws ServletException */ /*@Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { logger.info("登录成功"); response.setContentType("application/json;charset=UTF-8"); // 返回对象信息 response.getWriter().write(objectMapper.writeValueAsString(authentication)); }*/ @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { logger.info("登录成功"); // 返回json if (LoginResponseType.JSON.equals(securityProperties.getBrowser().getLoginType())) { response.setContentType("application/json;charset=UTF-8"); response.getWriter().write(objectMapper.writeValueAsString(authentication)); } else { // 父类的方法就是跳转网页 super.onAuthenticationSuccess(request, response, authentication); } } }