Spring Boot 无法登录
Posted
技术标签:
【中文标题】Spring Boot 无法登录【英文标题】:Unable to Login in Spring Boot 【发布时间】:2021-11-08 18:46:37 【问题描述】:我是 Spring Boot 新手,我正在尝试登录我的应用程序。我面临一些问题。 我无法登录。它无法验证以使用我的凭据登录并返回消息登录无效。 我希望用户在尝试访问客户端站点(例如 localhost:8080/)时进行身份验证。当用户对链接文件无效时,我还想实现注销。 这是我的主要应用程序
package oidc.controller;
import eu.olympus.client.interfaces.UserClient;
import eu.olympus.model.Attribute;
import eu.olympus.model.AttributeIdentityProof;
import eu.olympus.model.Operation;
import eu.olympus.model.Policy;
import eu.olympus.model.Predicate;
import eu.olympus.model.exceptions.AuthenticationFailedException;
import eu.olympus.model.exceptions.ExistingUserException;
import eu.olympus.model.exceptions.OperationFailedException;
import eu.olympus.model.exceptions.TokenGenerationException;
import eu.olympus.model.exceptions.UserCreationFailedException;
import eu.olympus.model.server.rest.IdentityProof;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import oidc.model.AttributeContainer;
import oidc.model.ChangeAttributesRequest;
import oidc.model.ChangePasswordRequest;
import oidc.model.CreateUserRequest;
import oidc.model.DeleteAccountRequest;
import oidc.model.LoginRequest;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.view.RedirectView;
@Controller
public class OidcController
private static final Logger logger = LoggerFactory.getLogger(OidcController.class);
@Autowired
UserClient userClient;
@Autowired
Policy policy;
// Login
@RequestMapping("/login")
public String login(Model model, @RequestParam String redirect_uri, @RequestParam String state, @RequestParam String nonce, HttpServletRequest request)
request.getSession().setAttribute("redirectUrl", redirect_uri);
request.getSession().setAttribute("state", state);
request.getSession().setAttribute("nonce", nonce);
LoginRequest loginRequest = new LoginRequest();
model.addAttribute("loginRequest", loginRequest);
policy.setPolicyId(nonce);
return "/login";
@RequestMapping("/loginFailed")
public String login(Model model)
LoginRequest loginRequest = new LoginRequest();
model.addAttribute("loginRequest", loginRequest);
model.addAttribute("loginError", true);
return "/login";
@RequestMapping("/loginPage")
public String loginPage(Model model)
LoginRequest loginRequest = new LoginRequest();
model.addAttribute("loginRequest", loginRequest);
model.addAttribute("hasCreated", false);
return "/login";
@PostMapping("/authenticate")
public RedirectView authenticate(LoginRequest loginRequest, Model model, HttpServletRequest request) throws AuthenticationFailedException, TokenGenerationException
try
// TODO We need to get the audience somehow?
policy.getPredicates().add(new Predicate("audience", Operation.REVEAL, new Attribute("olympus-service-provider")));
String token = userClient.authenticate(loginRequest.getUsername(), loginRequest.getPassword(), policy, null, "NONE");
model.addAttribute("username", loginRequest.getUsername());
model.addAttribute("token", token);
String redirectUrl = (String) request.getSession().getAttribute("redirectUrl");
String state = (String) request.getSession().getAttribute("state");
return new RedirectView(redirectUrl + "#state=" + state + "&id_token=" + token + "&token_type=bearer");
catch (Exception e)
e.printStackTrace();
if (ExceptionUtils.indexOfThrowable(e, AuthenticationFailedException.class) != -1)
return new RedirectView("/loginFailed", true);
else
throw e;
finally
userClient.clearSession();
这里是登录请求
package oidc.model;
import lombok.Getter;
import lombok.Setter;
/**
* A container for a login request
*/
@Getter
@Setter
public class LoginRequest
private String username;
private String password;
【问题讨论】:
如果您还没有使用 Spring Security,我建议您考虑将其添加到您的项目中,因为它默认提供登录功能。您可以将其中一个示例用作starting point,并查看参考documentation 【参考方案1】:我建议你使用Spring Security
。它是一个依赖项,您可以通过您的构建工具添加它,例如Maven
、Gradle
等。研究您的代码后,我可以看到您正在尝试从头开始构建安全机制。
我不建议您这样做,除非您有很高的动机这样做。如果您可以使用Spring Security
,它非常强大,并且配备了您正在寻找的所有功能。您可以轻松克服用户身份验证、授权,甚至可以提供默认登录页面。
在身份验证方面,您可以拥有几种类型的用户存储,例如内存用户存储、JDBC
用户存储、LDAP
用户存储甚至您自己的自定义用户存储。除了通过GUI
进行用户名和密码身份验证外,您还可以进行系统到系统身份验证。只需添加过滤器和次要配置等几个步骤,即可轻松实现JWT
令牌认证。
在这里很难涵盖并给出整个源代码作为答案,但我会为您提供一个示例代码,以便您可以一睹它的风采。请注意,以下代码仅用于演示目的,可以根据您的标准对其进行修改。
Spring 安全配置类
package com.example.sankalpaspringbootcicd.security;
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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
/**
* Security configuration class.
* Created date - 2021/08/02
*/
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
/**
* Authentication
* Responsible for configuring user-store.
* Overridden from WebSecurityConfigurerAdapter level.
* @param theAuthenticationManager AuthenticationManagerBuilder
* @throws Exception - Exception
*/
@Override
public void configure(AuthenticationManagerBuilder theAuthenticationManager) throws Exception
theAuthenticationManager.inMemoryAuthentication()
//Admin user
.withUser("admin")
.password("super")
.roles("ADMIN")
.and()
//Normal user
.withUser("user")
.password("password")
.roles("USER");
/**
* Authorization
* Responsible for security configuration.
* Overridden from WebSecurityConfigurerAdapter level.
* @param theHttpSecurity HttpSecurity
* @throws Exception - Exception
*/
@Override
public void configure(HttpSecurity theHttpSecurity) throws Exception
theHttpSecurity.csrf().disable();
theHttpSecurity
.authorizeRequests()
.antMatchers("/welcome/**").access("permitAll")
.antMatchers("/user/**").hasRole("ADMIN")
.anyRequest().fullyAuthenticated() //All requests should be authenticated
.and().headers().frameOptions().sameOrigin() //To allow H2-Console
.and().httpBasic();
/**
* Method constructing a password encoder bean.
* Constructs 'NoOpPasswordEncoder'.
* @return PasswordEncoder
*/
@Bean
public PasswordEncoder getPasswordEncoder()
return NoOpPasswordEncoder.getInstance();
这是一个非常简单的示例,我将带您了解每种方法。第一种方法是configure(AuthenticationManagerBuilder theAuthenticationManager)
,它的作用基本上是为您创建一个内存用户存储。
第二种方法是configure(HttpSecurity theHttpSecurity)
,它允许您对自己的安全行为进行自定义。它确实为每个人提供了一些路由,仅对具有特定角色的用户限制了一些路由,允许 H2 嵌入式数据库控制台的路由,禁用 CSRF
(跨站点请求伪造)等。这也会提示您一个默认登录页面.您还可以在此处进一步添加与您的登录和注销机制相关的逻辑。
第三种方法是PasswordEncoder getPasswordEncoder()
,它确实创建了一个密码编码器bean并将其放在Spring Application Context
中以供随时使用。
【讨论】:
以上是关于Spring Boot 无法登录的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot 和 OAuth2 社交登录,无法获取 refreshToken
为啥我登录后无法进入管理 REST API 请求映射 - Spring Boot
如何解决在使用 Spring Boot 和 Spring Security 启用 CSRF 后无法正常工作的登录问题?
在 Spring Boot 安全性中,无法跳过登录 url 的 OncePerRequestFilter 过滤器(基本上是在初始登录期间获取 JWT 令牌)