核心功能
- 认证(你是谁)
- 授权(你能干什么)
- 攻击防护(防止伪造身份)
一组过滤器链
//所有请求都需要认证 几乎是默认的
@Configuration
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin().and().authorizeRequests()
.anyRequest().authenticated(); //vt. 批准,认可;授权给;委托代替
http.httpBasic();
#security.basic.enabled = false
使用密码加密
@Configuration
public class AuthenticationBeanConfig {
/**
* 默认密码处理器
* @return
*/
@Bean
@ConditionalOnMissingBean(PasswordEncoder.class)
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
定义认证授权 用户名密码
@Component
@Transactional
public class DemoUserDetailsService implements UserDetailsService
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// logger.info("表单登录用户名:" + username);
// Admin admin = adminRepository.findByUsername(username);
// admin.getUrls();
// return admin;
return buildUser(username); //直接new User 也行
}
private SocialUserDetails buildUser(String userId) { //返回user也行
// 根据用户名查找用户信息
//根据查找到的用户信息判断用户是否被冻结
String password = passwordEncoder.encode("123456");
logger.info("数据库密码是:"+password);
return new SocialUser(userId, password,
true, true, true, true,
AuthorityUtils.commaSeparatedStringToAuthorityList("xxx"));
}
实现不同样式的请求,不同样式的转发
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin()
.loginPage("/imooc-signIn.html") //在resource 下简历 resource文件夹,里面有此html
.loginProcessingUrl("/authentication/form")
.and().authorizeRequests()
.antMatchers("/imooc-signIn.html").permitAll() //同理这里也要加入,自定义的登录页面,不需要权限认证
.anyRequest().authenticated()
.and().csrf().disable();
就是把html界面,换成请求,
@RestController
public class BrowserSecurityController {
private Logger logger = LoggerFactory.getLogger(getClass());
private RequestCache requestCache = new HttpSessionRequestCache();
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
@Autowired
private SecurityProperties securityProperties;
@RequestMapping(SecurityConstants.DEFAULT__URL)
@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();
logger.info("引发跳转的请求是:" + targetUrl);
if (StringUtils.endsWithIgnoreCase(targetUrl, ".html")) {
redirectStrategy.sendRedirect(request, response, securityProperties.getBrowser().getSignInPage()); //如果用户配置了值,就用,没有用默认的值
}
}
return new SimpleResponse("访问的服务需要身份认证,请引导用户到登录页");
}
public class SimpleResponse {
private Object content;
}
配置文件
@ConfigurationProperties(prefix = "imooc.security")
public class SecurityProperties {
// 浏览器环境配置
private BrowserProperties browser = new BrowserProperties(); //browser下面有loginPage 就能读取到下面的配置
让读取器生效:
@Configuration
@EnableConfigurationProperties(SecurityProperties.class)
public class SecurityCoreConfig {
}
自定义登录成功处理
SavedRequestAwareAuthenticationSuccessHandler 是 AuthenticationSuccessHandler 实现类,这里用AuthenticationSuccessHandler
@Component("imoocAuthenticationSuccessHandler")
public class ImoocAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
private Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private ObjectMapper objectMapper;
@Autowired
private SecurityProperties securityProperties;
private RequestCache requestCache = new HttpSessionRequestCache();
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
logger.info("登录成功");
if (LoginResponseType.JSON.equals(securityProperties.getBrowser().getSignInResponseType())) {
response.setContentType("application/json;charset=UTF-8");
String type = authentication.getClass().getSimpleName();
response.getWriter().write(objectMapper.writeValueAsString(new SimpleResponse(type)));
} else {
// 如果设置了imooc.security.browser.singInSuccessUrl,总是跳到设置的地址上
// 如果没设置,则尝试跳转到登录之前访问的地址上,如果登录前访问地址为空,则跳到网站根路径上
if (StringUtils.isNotBlank(securityProperties.getBrowser().getSingInSuccessUrl())) {
requestCache.removeRequest(request, response);
setAlwaysUseDefaultTargetUrl(true);
setDefaultTargetUrl(securityProperties.getBrowser().getSingInSuccessUrl());
}
super.onAuthenticationSuccess(request, response, authentication);
}
}
}
@Configuration
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {
@Component
public class FormAuthenticationConfig {
@Autowired
protected AuthenticationSuccessHandler imoocAuthenticationSuccessHandler;
@Autowired
protected AuthenticationFailureHandler imoocAuthenticationFailureHandler;
public void configure(HttpSecurity http) throws Exception {
http.formLogin()
.loginPage(SecurityConstants.DEFAULT_UNAUTHENTICATION_URL)
.loginProcessingUrl(SecurityConstants.DEFAULT_SIGN_IN_PROCESSING_URL_FORM)
.successHandler(imoocAuthenticationSuccessHandler)
.failureHandler(imoocAuthenticationFailureHandler);
}
}
错误的处理
@Component("imoocAuthenctiationFailureHandler")
public class ImoocAuthenctiationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
private Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private ObjectMapper objectMapper;
@Autowired
private SecurityProperties securityProperties;
/* (non-Javadoc)
* @see org.springframework.security.web.authentication.AuthenticationFailureHandler#onAuthenticationFailure(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, org.springframework.security.core.AuthenticationException)
*/
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException {
logger.info("登录失败");
if (LoginResponseType.JSON.equals(securityProperties.getBrowser().getSignInResponseType())) {
response.setStatus(HttpStatus.UNAUTHORIZED.value());
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write(objectMapper.writeValueAsString(new SimpleResponse(exception.getMessage())));
}else{
super.onAuthenticationFailure(request, response, exception);
}
}
}
同理配置到 failureHandler
配置:
imooc.security.browser.signInResponseType = REDIRECT