校长为空:春天

Posted

技术标签:

【中文标题】校长为空:春天【英文标题】:Principal is null: Spring 【发布时间】:2019-03-25 19:17:24 【问题描述】:

我有以下@RestContoller 用于登录:

  @RequestMapping("/account/login")
@ResponseBody
@CrossOrigin(origins = "*", maxAge = 3600)
public Principal login(Principal principal) 
    logger.info("user logged " + principal.getName());
    return principal;

我有一个 Angularjs 应用程序客户端提出的以下请求。

Accept: application/json
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,fa;q=0.8,it;q=0.7
Authorization: Basic bWVocmRhZGFsbGFoa2FyYW1pQGdtYWlsLmNvbTptZWhyZGFk
Connection: keep-alive
DNT: 1
Host: localhost:8080
Origin: http://localhost:4200
Referer: http://localhost:4200/login
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/67.0.3396.62 Safari/537.36

但是我得到200 作为响应,服务器打印null 并且客户端得到错误响应:

HttpErrorResponse headers: HttpHeaders, status: 400, statusText: "OK", url: "http://localhost:8080/account/login", ok: false, …error: timestamp: 1540136257516, status: 400, error: "Bad Request", exception: "org.springframework.web.bind.ServletRequestBindingException", message: "Missing request header 'header' for method parameter of type Header", …headers: HttpHeaders normalizedNames: Map(0), lazyUpdate: null, lazyInit: ƒmessage: "Http failure response for http://localhost:8080/account/login: 400 OK"name: "HttpErrorResponse"ok: falsestatus: 400statusText: "OK"url: "http://localhost:8080/account/login"__proto__: HttpResponseBase

谁能帮我知道我哪里错了?它以前可以工作,但我在 Angular 中使用了拦截器,它不再工作了。

我的登录控制器是这样的:

@Injectable()
export class AuthService 
  constructor(public http: HttpClient, public auth: InterceptorAuthService) 
  

  public logIn(user: User) 
    this.auth.setUser(user);
    return this.http.get(AppComponent.API_URL + "/account/login")
      .pipe(
        map(response => 
            // login successful if there's a jwt token in the response
            let user = response;// the returned user object is a principal object
            if (user) 
              // store user details  in local storage to keep user logged in between page refreshes
              localStorage.setItem('currentUser', JSON.stringify(user));
            
          ,
          catchError(error => 
            return Observable.throw(error);
          )
        ));
  

WebConfig.java 配置:

// This method is used for override HttpSecurity of the web Application.
// We can specify our authorization criteria inside this method.
@Override
protected void configure(HttpSecurity http) throws Exception 
    // @formatter:off
    // ignoring the guest's urls "
    http.antMatcher("/account/**").authorizeRequests().anyRequest().authenticated().and()
            .antMatcher("/token").authorizeRequests().anyRequest().authenticated()
            .antMatchers("/logout").permitAll()
            .and()
            .csrf()
            .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and()
            .httpBasic();
    // authenticate all remaining URLS

    // @formatter:on

【问题讨论】:

你读过***.com/questions/31159075/…吗? @ChirdeepTomar 是的,我实际上使用的是基本安全主体,但它为空。您还有其他我可以使用的安全方法吗?我研究了一天,还没有得到合乎逻辑的结果 @dur 是的,我得到了 NullExeption 的所有解决方案 我很想知道 SecurityContextHolder.getContext().getAuthentication() 在您尝试获取原理的登录控制器方法中为您提供了什么。在进一步操作之前检查您的 securityContext 是否设置正确 @dur 客户端 URL 是 localhost:4200/login 并且接受此请求的服务器 URL 是 localhost:8080/account/login 【参考方案1】:

尝试将sec:authorize="isAuthenticated() 添加到要显示用户名的“/account/login”模板中

例如:

<h3 sec:authorize="isAuthenticated()" th:text="$user.username"></h3>  

如果已经发生,它将获取身份验证状态,否则,它将不会显示&lt;h3&gt; 代码块。

【讨论】:

【参考方案2】:
@Component
public class MyBasicAuthenticationEntryPoint extends BasicAuthenticationEntryPoint 
@Override
public void afterPropertiesSet() throws Exception 
    setRealmName("Baeldung");
    super.afterPropertiesSet();

@Override
public void commence(
  HttpServletRequest request, HttpServletResponse response, AuthenticationException authEx) 
  throws IOException, ServletException 
    response.addHeader("WWW-Authenticate", "Basic realm="" + getRealmName() + """);
    response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
    PrintWriter writer = response.getWriter();
    writer.println("HTTP Status 401 - " + authEx.getMessage());



// inside filter we can get the 
SecurityContextHolder.getContext().getAuthentication().getPrincipal()

【讨论】:

你可以查看文档baeldung.com/spring-security-basic-authentication

以上是关于校长为空:春天的主要内容,如果未能解决你的问题,请参考以下文章

如果它为空或为空,如何从序列化中忽略可为空的属性?

MySQL:判断字段是不是为空

“不为空”和“不为空”有啥区别

php 判断一个字段是不是为空,为空的话执行一段sql语句

session为空的问题

检查字符串是不是不为空且不为空