#spring-boot #authentication #spring-security #single-sign-on #spring-security-oauth2
Вопрос:
Я создаю проект с spring security для входа в систему с помощью единого входа Oauth, это часть моего проекта, использующая Spring Security 5, jQuery для вызова ajax, spring-security-oauth2 и spring-security-oauth2-автоконфигурация для авторизации и сервера ресурсов в одном проекте Spring Boot 2, я хочу использовать пользовательскую страницу входа и единый вход для многих клиентов. Я поискал вокруг, но я закончил с пользовательской страницей входа, достигнутой с помощью uri:http://localhost:8080/oauth/authorize?grant_type=authorization_codeamp;response_type=codeamp;client_id=SampleClientIdamp;state=1234 но после вставки учетных данных для входа приложение не перенаправляется на клиент Oauth, и сеанс не является общим, и оно всегда будет запрашивать вход,
это мой класс конфигурации безопасности
@Configuration
@Order(1)
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private static final String PROD = "prod";
private static final RequestMatcher PUBLIC_URLS = new OrRequestMatcher(
new AntPathRequestMatcher("/error"),
new AntPathRequestMatcher("/register/v1"),
// -- dash
new AntPathRequestMatcher("/html/*.html"),
new AntPathRequestMatcher("/css/**"),
new AntPathRequestMatcher("/js/**"),
new AntPathRequestMatcher("/favicon.ico"),
new AntPathRequestMatcher("/*.html"),
new AntPathRequestMatcher("/login/v1"),
new AntPathRequestMatcher("/resetPassword/v1"),
new AntPathRequestMatcher("/resetPasswordOk"),
new AntPathRequestMatcher("/changePassword/**"),
new AntPathRequestMatcher("/updatePassword/**"),
new AntPathRequestMatcher("/savePassword/**"),
new AntPathRequestMatcher("/config"),
new AntPathRequestMatcher("/auth/**"),
new AntPathRequestMatcher("/oauth/authorize"),
new AntPathRequestMatcher("/oauth/token")
);
private static final RequestMatcher PUBLIC_URLS_TEST = new OrRequestMatcher(
new AntPathRequestMatcher("/error"),
new AntPathRequestMatcher("/register/v1"),
// -- swagger ui
new AntPathRequestMatcher("/swagger-resources/**"),
//new AntPathRequestMatcher("/swagger-ui.html"),
new AntPathRequestMatcher("/swagger.html"),
new AntPathRequestMatcher("/v2/api-docs"),
new AntPathRequestMatcher("/webjars/**"),
// -- dash
new AntPathRequestMatcher("/html/*.html"),
new AntPathRequestMatcher("/css/**"),
new AntPathRequestMatcher("/js/**"),
new AntPathRequestMatcher("/favicon.ico"),
new AntPathRequestMatcher("/*.html"),
new AntPathRequestMatcher("/login/v1"),
new AntPathRequestMatcher("/resetPassword/v1"),
new AntPathRequestMatcher("/resetPasswordOk"),
new AntPathRequestMatcher("/changePassword/**"),
new AntPathRequestMatcher("/updatePassword/**"),
new AntPathRequestMatcher("/savePassword/**"),
new AntPathRequestMatcher("/config"),
new AntPathRequestMatcher("/auth**"),
new AntPathRequestMatcher("/oauth/authorize"),
new AntPathRequestMatcher("/oauth/token")
);
private static final RequestMatcher PROTECTED_URLS = new NegatedRequestMatcher(PUBLIC_URLS);
@Autowired
private TokenAuthenticationProvider authenticationProvider;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception{
auth.authenticationProvider(authenticationProvider);
}
@Override
public void configure(WebSecurity web) {
if (config.getEnv().equalsIgnoreCase(PROD)) {
web.ignoring().requestMatchers(PUBLIC_URLS);
}else {
web.ignoring().requestMatchers(PUBLIC_URLS_TEST);
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement().sessionCreationPolicy(STATELESS)
.and()
.exceptionHandling().accessDeniedHandler(accessDeniedHandler())
.defaultAuthenticationEntryPointFor(forbiddenEntryPoint(), PROTECTED_URLS)
.and()
.authenticationProvider(authenticationProvider)
.addFilterBefore(restAuthenticationFilter(), AnonymousAuthenticationFilter.class)
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login.html")
.usernameParameter("username")
.passwordParameter("password")
.loginProcessingUrl("/login/v1")
.failureUrl("/login.html?error=true")
.and()
.logout()
.logoutUrl("/logout")
.deleteCookies("JSESSIONID")
.and()
.csrf().disable()
;
}
@Bean
TokenAuthenticationFilter restAuthenticationFilter() throws Exception {
TokenAuthenticationFilter filter = new TokenAuthenticationFilter(PROTECTED_URLS);
filter.setAuthenticationManager(authenticationManager());
filter.setAuthenticationFailureHandler(failureHandler());
return filter;
}
private AuthenticationFailureHandler failureHandler() {
return new CustomAuthenticationFailureHandler();
}
private AccessDeniedHandler accessDeniedHandler() {
return new CustomAccessDeniedHandler();
}
@Bean
FilterRegistrationBean<TokenAuthenticationFilter> disableAutoRegistration(TokenAuthenticationFilter filter) {
FilterRegistrationBean<TokenAuthenticationFilter> registration = new FilterRegistrationBean<TokenAuthenticationFilter>(filter);
registration.setEnabled(false);
return registration;
}
@Bean
AuthenticationEntryPoint forbiddenEntryPoint() {
return new HttpStatusEntryPoint(FORBIDDEN);
}
@Bean
public CustomPasswordEncoder passwordEncoder() {
return new CustomPasswordEncoder();
}
}
это мой класс конфигурации сервера авторизации:
@Configuration
@EnableAuthorizationServer
public class OAuth2Config extends AuthorizationServerConfigurerAdapter {
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception{
clients.inMemory()
.withClient("SampleClientId")
.secret(passwordEncoder3.encode("secret"))
.scopes("resource:read")
.authorizedGrantTypes("authorization_code")
.redirectUris("http://localhost:8082/app1")
//.redirectUris("http://localhost:8081/oauth/login/client-app");
.autoApprove(true);
}
private final PasswordEncoder passwordEncoder3;
public OAuth2Config(PasswordEncoder passwordEncoder) {
this.passwordEncoder3 = passwordEncoder;
}
@Override
public void configure(
AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
}
}
this is my Spring Boot app class:
@EnableResourceServer
@SpringBootApplication
public class Application{
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:messages");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
@Bean
public LocalValidatorFactoryBean getValidator() {
LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
bean.setValidationMessageSource(messageSource());
return bean;
}
}
this is my custom login page that I’ve created:
<body>
<div class="form-signin">
<form th:action="@{/login/v1}" method="post" style="max-width: 350px; margin: 0 auto;">
<!--<div th:if="${param.error}" class="alert alert-error">Invalid username and password.</div>
<div th:if="${param.logout}" class="alert alert-success">You have been logged out.</div>-->
<div class="form-label-group" id="username-group">
<input id="username" name="username" class="form-control" placeholder="Username" required autofocus> <label for="username">Utente</label>
</div>
<div class="form-label-group" id="password-group">
<input type="password" id="password" name="password" class="form-control" placeholder="Password" required> <label for="password">Password</label>
</div>
<p id="label-login-action"></p>
<button class="btn btn-lg btn-secondary btn-block" type="submit" id="login">Login</button>
<p class="mt-5 mb-3 text-muted text-center">amp;copy; 2016-2020</p>
</form>
</div>
<script>
$(document).ready(function () {
Cookies.remove("token");
$("#login").on("click", function(){
login($("#username").val(),$("#password").val(), $("#tfauth").val());
});
$("#password").on("keydown", function(e){
if (e.which == 13) {
$("#login").click();
}
})
});
</script>
это мой вызов jquery с ajax
var login = function(username, password, code) {
var loginLabel = $("#label-login-action");
loginLabel.removeClass("alert-danger");
loginLabel.addClass("alert alert-warning");
loginLabel.html("Logging...");
var endpoint = config.path "/login/v1";
$.postJSON2(endpoint, {
username : username,
password : password,
code : code
}, function(response) {
if (response.token) {
Cookies.remove('lastError');
Cookies.set('token', response.token);
goToPage("index");
}, function(request, status, error) {});
}
и контроллер REST для входа в систему
@PostMapping(path = "/login", consumes = "application/json", produces = "application/json")
public UserLoginResponse login(@Valid @RequestBody UserLoginRequest user, BindingResult bindingResult,
HttpServletRequest request, HttpServletResponse response, Locale locale) throws Exception {
...
}
Комментарии:
1. Похоже, вы используете устаревший
spring-security-oauth
проект. Пожалуйста, вместо этого используйте поддержку OAuth 2.0, предоставляемую Spring Security .