@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private final ObjectMapper objectMapper = new ObjectMapper();
/**
* 这些接口 对于认证中心来说无需授权
*/
protected static final String[] PERMIT_ALL_URL = {"/oauth/**", "/user/**", "/actuator/**", "/error", "/open/api"};
@Resource
private AuthenticationProvider myAuthenticationProvider;
@Resource
private AuthCommonConfig authCommonConfig;
@Value("${spring.profiles.active}")
private String profile;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors()
.and().csrf().disable()
.authorizeRequests()
//处理跨域请求中的Preflight请求
.antMatchers(HttpMethod.OPTIONS).permitAll()
.requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
.antMatchers(PERMIT_ALL_URL)
.permitAll()
.and()
.formLogin()
// .loginPage(authCommonConfig.getLoginPage())
.loginProcessingUrl("/login")
.usernameParameter("username")
.passwordParameter("password")
.successHandler(authenticationSuccessHandler())
.failureHandler(authenticationFailureHandler())
.and().logout()
.logoutSuccessHandler(logoutSuccessHandler())
.deleteCookies("SESSIONID")
// .and().httpBasic()
;
}
public static void main(String[] args) {
System.out.println(new BCryptPasswordEncoder().encode("123456"));
System.out.println(PasswordEncoderFactories.createDelegatingPasswordEncoder().encode("123456"));
System.out.println(PasswordEncoderFactories.createDelegatingPasswordEncoder().matches("123456", "{bcrypt}$2a$10$tuMR8ca2nM5miqc6cNHlxOjQrtOIDPVCpTt69jwTOcsEgIEBYFfjm"));
}
/**
* 登录成功处理器
*/
@Bean
public AuthenticationSuccessHandler authenticationSuccessHandler() {
return (httpServletRequest, httpServletResponse, authentication) -> {
// RequestCache requestCache = new HttpSessionRequestCache();
// SavedRequest savedRequest = requestCache.getRequest(httpServletRequest, httpServletResponse);
// String targetUrl = savedRequest.getRedirectUrl();
httpServletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
String state = httpServletRequest.getParameter("state");
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(authCommonConfig.getAuthDomain() +
"/auth/oauth/authorize")
.queryParam("response_type", "code")
.queryParam("state", httpServletRequest.getParameter("state"))
.queryParam("client_id", httpServletRequest.getParameter("client_id"))
.queryParam("redirect_uri", httpServletRequest.getParameter("redirect_uri"))
.queryParam("scope", httpServletRequest.getParameter("scope"));
String redirectUrl = builder.encode().toUriString();
if (Objects.equals("dev", profile)) {
httpServletResponse.sendRedirect(redirectUrl);
return;
}
//如果不确定,则默认跳回用户中心
httpServletResponse.getWriter().write(objectMapper.writeValueAsString(ResultModel.success(
redirectUrl
)));
return;
};
}
/**
* 登出成功处理器
*/
@Bean
public LogoutSuccessHandler logoutSuccessHandler() {
return (httpServletRequest, httpServletResponse, authentication) -> {
httpServletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
httpServletResponse.getWriter().write(objectMapper.writeValueAsString(ResultModel.success()));
};
}
/**
* 常规登录失败处理器
*/
@Bean
public AuthenticationFailureHandler authenticationFailureHandler() {
return (httpServletRequest, httpServletResponse, e) -> {
httpServletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
httpServletResponse.setCharacterEncoding("UTF-8");
httpServletResponse.setStatus(HttpStatus.UNAUTHORIZED.value());
String message = "登录失败";
if (e instanceof UsernameNotFoundException) {
message = e.getMessage();
}
if (e instanceof BadCredentialsException) {
message = e.getMessage();
}
if (e instanceof AccountExpiredException) {
message = e.getMessage();
}
httpServletResponse.getWriter().write(objectMapper.writeValueAsString(ResultModel.fail(
String.valueOf(HttpStatus.UNAUTHORIZED.value()), message)
));
};
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(this.myAuthenticationProvider);
// auth.userDetailsService(oauthAccountUserDetailsService).passwordEncoder(passwordEncoder());
auth.eraseCredentials(true);
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
// @Bean
// public UrlBasedViewResolver UrlBasedViewResolver() throws Exception {
// UrlBasedViewResolver v = new UrlBasedViewResolver();
// v.setRedirectHttp10Compatible(false);
// v.setViewClass(RedirectView.class);
// return v;
// }
// @Bean
// public DefaultRedirectStrategy DefaultRedirectStrategy() throws Exception {
// DefaultRedirectStrategy v = new DefaultRedirectStrategy();
// v.setContextRelative(true);
// return v;
// }
}
自己实现账号密码验证规则
@Component @Slf4j public class MyAuthenticationProvider implements AuthenticationProvider { @Resource private RestTemplate restTemplate; @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { String username = authentication.getName(); String password = (String) authentication.getCredentials(); String clientId = getClientIdByRequest(); Map<String, String> paramMap = new HashMap<>(); paramMap.put("username", username); paramMap.put("password", password); paramMap.put("clientId", clientId); UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl("http://uc-user-service/user/v1/rpc/user/loadUserByUsername"); paramMap.forEach(builder::queryParam); String result = restTemplate.getForObject(builder.encode().toUriString(), String.class, paramMap); log.info("用户登录:{}->{}", username, result); ResultModel<LoginUserVO> resultModel = JsonUtils.string2Obj(result, new TypeReference<ResultModel<LoginUserVO>>() { }); // 根据用户名获取用户信息 if (!resultModel.isSuccess()) { throw new BadCredentialsException(resultModel.getMessage()); } else { LoginUserVO account = resultModel.getData(); return new UsernamePasswordAuthenticationToken( new OauthAccountUserDetails(account, new ArrayList<>()), authentication.getCredentials(), emptyList()); } } public String getClientIdByRequest() { ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); if (attributes == null) throw new UnsupportedOperationException(); HttpServletRequest request = attributes.getRequest(); String clientId = request.getParameter("client_id"); if (StringUtils.isNotEmpty(clientId)) { return clientId; } String auth = request.getHeader("Authorization"); auth = StringUtils.substringAfter(auth, "Basic "); return new String(Base64.getDecoder().decode(auth)).split(":")[0]; } @Override public boolean supports(Class<?> authentication) { return true; } }