嗨,我在邮递员中有此要求。
如何在Reactjs axios中发出相同的请求?
executeAuthenticationService(username, password) {
return axios.get(`${API_URL}/oauth/token?grant_type=password&username=${username}&password=${password}`,
{ headers: { Authorization: 'Basic ' + window.btoa('my-trusted-client : secret') } } )
.catch(
(error) => {
console.log('error: ' + error);
}
);
}
我尝试了上面的方法,但是没有用。 谢谢
============== 更新: ==============
我已按照您的建议删除了空格。当涉及到window.btoa时,不带空格的转换似乎是准确的,但我仍然无法使其正常工作。
使用以下代码:
executeAuthenticationService(username, password) {
return axios.get(`${API_URL}/oauth/token?grant_type=password&username=${username}&password=${password}`,
{
headers:
{
Authorization: 'Basic ' + window.btoa('my-trusted-client:secret'),
"Content-Type": "application/json"
}
})
.catch(
(error) => {
console.log('error: ' + error);
}
);
}
我什至将Authorization标头硬编码为:
Authorization: "Basic bXktdHJ1c3RlZC1jbGllbnQ6c2VjcmV0",
甚至尝试过:
"Authorization": "Basic bXktdHJ1c3RlZC1jbGllbnQ6c2VjcmV0",
没有任何效果,授权标头不会出现在请求中。
我在Chrome的“网络”标签中找到了该标签:
我发现我可以在axios中添加身份验证配置,所以我尝试了这一操作:
executeAuthenticationService(username, password) {
return axios.get(`${API_URL}/oauth/token?grant_type=password&username=${username}&password=${password}`,
{
headers:
{
"Content-Type": "application/json"
},
auth: {
username: 'my-trusted-client',
password: 'secret'
}
})
.catch(
(error) => {
console.log('error: ' + error);
}
);
}
仍然,没有授权标头...请帮助。谢谢。
============== Update2 =============
我要添加一些信息。
我的Springboot配置如下:
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowCredentials(true)
.allowedHeaders("Authorization", "Cache-Control", "Content-Type", "Accept", "X-Requested-With", "Access-Control-Allow-Origin", "Access-Control-Allow-Headers", "Origin")
.exposedHeaders("Access-Control-Expose-Headers", "Authorization", "Cache-Control", "Content-Type", "Access-Control-Allow-Origin", "Access-Control-Allow-Headers", "Origin")
.allowedMethods("GET", "OPTIONS", "POST", "PUT", "DELETE", "PATCH");
}
}
我最后使用的reactJS请求是这样的:
executeAuthenticationService(username, password) {
return axios.get(`${API_URL}/oauth/token?grant_type=password&username=${username}&password=${password}`,
{
headers:
{
"Content-Type": "application/json"
},
auth: {
username: 'my-trusted-client',
password: 'secret'
}
})
.catch(
(error) => {
console.log('error: ' + error);
}
);
}
当我从登录表单中单击“提交”按钮
我是从Chrome标签中获得的(整个内容):
然后我在Java控制台上得到它:
2019-07-11 06:40:47.008 DEBUG 8068 --- [io-8080-exec-10] o.s.web.servlet.DispatcherServlet : "ERROR" dispatch for OPTIONS "/error?grant_type=password&username=bill&password=abc123", parameters={masked}
2019-07-11 06:40:47.009 DEBUG 8068 --- [io-8080-exec-10] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to public void org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$EmptyHandler.handle()
2019-07-11 06:40:47.010 DEBUG 8068 --- [io-8080-exec-10] o.s.web.servlet.DispatcherServlet : Exiting from "ERROR" dispatch, status 401
我不知道我还想念什么。 请帮忙。 非常感谢。
答案 0 :(得分:0)
尝试一下(删除空格):
headers: {
Authorization: 'Basic ' + window.btoa('my-trusted-client:secret')
}
答案 1 :(得分:0)
您可以尝试以下方法:
axios.get(`${API_URL}/oauth/token?grant_type=password&username=${username}&password=${password}`,
{
headers: {
Authorization: "Basic " + window.btoa("my-trusted-client : secret"),
"Content-Type": "application/json",
},
}
)
.then(resp => {})
.catch(error => {
console.log("error: " + error);
});
答案 2 :(得分:0)
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
您可以尝试设置所有请求的标题
答案 3 :(得分:0)
是否可能是您缺少Access-Control-Allow-Methods上OPTIONS的方法?
这意味着您甚至在生成整个请求之前都会被拒绝?
或者可能会禁用您的OPTIONS请求作为授权的一部分,类似于在这里进行的操作:https://www.baeldung.com/spring-security-cors-preflight
答案 4 :(得分:0)
在使用Spring和Axios进行基本身份验证时,我失去了试图处理此类问题的渴望。
在尝试了几乎所有内容之后,甚至像您一样进行配置之后,我也找到了适用于您的用例的解决方案。
Axios请求
我使用Axios这样的请求,请注意这里有一个auth参数:
async removeAnexo(uuidAnexo, successCallback, errorCallback) {
const credentials = JSON.parse(Cookies.get("credentials"));
const axiosRequest = axios.create({
baseURL: serverUrl,
auth: {
username: credentials.username,
password: credentials.password
},
headers: {
"Content-Type": "application/json"
}
});
await axiosRequest
.post("processos/anexo/" + uuidAnexo + "/remove")
.then(res => {
if (res.status === 200) {
successCallback();
return res;
}
})
.catch(error => {
errorCallback(error);
});
}
春季配置
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;
import org.springframework.stereotype.Component;
@Component
public class AuthEntryPoint extends BasicAuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
org.springframework.security.core.AuthenticationException authException)
throws IOException, ServletException {
if (HttpMethod.OPTIONS.matches( request.getMethod() )) {
response.setStatus( HttpServletResponse.SC_OK );
response.setHeader( HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, request.getHeader( HttpHeaders.ORIGIN ) );
response.setHeader( HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, request.getHeader( HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS ) );
response.setHeader( HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, request.getHeader( HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD ) );
response.setHeader( HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, "*" );
response.setHeader( HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true" );
} else {
response.sendError( HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage() );
}
}
@Override
public void afterPropertiesSet() throws Exception {
this.setRealmName( "simpleRealm" );
super.afterPropertiesSet();
}
}
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
@Component
public class CorsFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) servletResponse;
HttpServletRequest request = (HttpServletRequest) servletRequest;
response.setHeader( "Access-Control-Allow-Origin", request.getHeader( "Origin" ) );
response.setHeader( "Access-Control-Allow-Methods", "GET,POST,DELETE,PUT,OPTIONS" );
response.setHeader( "Access-Control-Allow-Headers", "*" );
response.setHeader( "Access-Control-Allow-Credentials", "true" );
response.setHeader( "Access-Control-Expose-Headers", "Content-Disposition,X-Suggested-Filename,X-Auth-Token,Authorization" );
response.setHeader( "Access-Control-Max-Age", "180" );
filterChain.doFilter( servletRequest, servletResponse );
}
@Override
public void destroy() {
}
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.core.env.Profiles;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import com.pontosistemas.clif.entities.system.Login;
import com.pontosistemas.clif.repositories.system.LoginRepository;
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
@Autowired
private LoginRepository loginRepository;
@Autowired
private Environment env;
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public Authentication authenticate(Authentication auth) throws AuthenticationException {
boolean notProductionProfile = env.acceptsProfiles( Profiles.of( "default", "homolog" ) );
String username = auth.getName();
String password = auth.getCredentials().toString();
if (notProductionProfile && "admin".equals( username ) && "admin".equals( password )) {
return new UsernamePasswordAuthenticationToken( username, password, Arrays.asList( new SimpleGrantedAuthority( "ADMIN" ), new SimpleGrantedAuthority( "protected" ) ) );
} else {
boolean usernameActiveExists = loginRepository.existsLoginByUsernameAndActiveIsTrue( username );
if (usernameActiveExists) {
Login login = loginRepository.findByUsernameAndActiveIsTrue( username );
String hashPassword = login.getPassword();
boolean matches = passwordEncoder.matches( password, hashPassword );
if (matches)
return new UsernamePasswordAuthenticationToken( username, hashPassword, Arrays.asList( new SimpleGrantedAuthority( login.getRole().toString() ), new SimpleGrantedAuthority( "protected" ) ) );
else
throw new BadCredentialsException( "Senha inválida!" );
}
}
throw new UsernameNotFoundException( "Nome de usuário não encontrado" );
}
@Override
public boolean supports(Class<?> auth) {
return auth.equals( UsernamePasswordAuthenticationToken.class );
}
}
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
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.config.http.SessionCreationPolicy;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.session.SessionManagementFilter;
import com.fasterxml.jackson.databind.ObjectMapper;
@Configuration
@EnableWebSecurity
public class BasicSecurityAdapter extends WebSecurityConfigurerAdapter {
@Autowired
private AuthEntryPoint authEntryPoint;
@Autowired
private CustomAuthenticationProvider customAuthProvider;
@Autowired
private CorsFilter corsFilter;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.addFilterBefore( corsFilter, SessionManagementFilter.class );
http.headers().frameOptions().disable();
http.httpBasic().authenticationEntryPoint( authEntryPoint );
http.authenticationProvider( customAuthProvider );
http
.authorizeRequests()
.antMatchers( "/public/**" ).permitAll()
.antMatchers( HttpMethod.OPTIONS, "/**" ).permitAll()
.antMatchers( "/**" ).hasAuthority( "protected" )
.anyRequest().authenticated()
.and()
.sessionManagement()
.sessionCreationPolicy( SessionCreationPolicy.STATELESS );
http.formLogin().loginProcessingUrl( "/login" );
http.formLogin().successHandler( new AuthenticationSuccessHandler() {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
response.addHeader( "Access-Control-Expose-Headers", "role" );
response.setHeader( "Access-Control-Allow-Origin", request.getHeader( "Origin" ) );
response.setHeader( "Access-Control-Allow-Methods", "GET,POST,DELETE,PUT,OPTIONS" );
response.setHeader( "Access-Control-Allow-Headers", "*" );
response.setHeader( "Access-Control-Allow-Credentials", "true" );
response.setHeader( "Access-Control-Expose-Headers", "Content-Disposition,X-Suggested-Filename,X-Auth-Token,Authorization" );
response.setHeader( "Access-Control-Max-Age", "180" );
String role = authentication.getAuthorities().stream().findFirst().get().toString();
response.addHeader( "role", role );
ObjectMapper objectMapper = new ObjectMapper();
Map<String, Object> data = new HashMap<String, Object>();
data.put( "role", role );
response.getWriter().print( objectMapper.writeValueAsString( data ) );
}
} );
http.formLogin().failureHandler( new AuthenticationFailureHandler() {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException {
response.addHeader( "Access-Control-Expose-Headers", "role" );
response.setHeader( "Access-Control-Allow-Origin", request.getHeader( "Origin" ) );
response.setHeader( "Access-Control-Allow-Methods", "GET,POST,DELETE,PUT,OPTIONS" );
response.setHeader( "Access-Control-Allow-Headers", "*" );
response.setHeader( "Content-type", "application/json; charset=UTF-8" );
response.setCharacterEncoding( "UTF-8" );
response.setStatus( HttpServletResponse.SC_UNAUTHORIZED );
ObjectMapper objectMapper = new ObjectMapper();
Map<String, String> data = new HashMap<String, String>();
data.put( "message", exception.getMessage() );
response.getWriter().print( objectMapper.writeValueAsString( data ) );
}
} );
http.logout().logoutSuccessHandler( (request, response, authentication) -> {
response.setHeader( "Access-Control-Allow-Origin", request.getHeader( "Origin" ) );
response.setHeader( "Access-Control-Allow-Methods", "GET,POST,DELETE,PUT,OPTIONS" );
response.setHeader( "Access-Control-Allow-Headers", "*" );
response.setStatus( HttpServletResponse.SC_OK );
} );
}
}
我的用例
在我的场景中,当用户登录时,我将用户登录名和密码存储在cookie上,并在调用API时携带这些凭据。
我相信您可以从基本身份验证更改为尝试更改CustomAuthenticationProvider的另一个选项。
也许对您来说有点晚了,但我希望这对某人有帮助。