如何修复Spring Rest和Ajax中的OPTIONS 401未经授权的错误?

时间:2019-01-02 12:42:30

标签: java ajax spring spring-mvc spring-rest

我正在尝试获取sprint mvc rest中的api的get请求,在控制台中出现以下错误:

OPTIONS http://localhost:8080/api/users/travel-plan/1 401 (Unauthorized)
Access to XMLHttpRequest at 'http://localhost:8080/api/users/travel-plan/1' from origin 'http://localhost:8585' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

以下是ajax请求的代码:

axios.get('http://localhost:8080/api/users/travel-plan/1',{
            headers: {
                'Access-Control-Allow-Origin': '*',
                Authorization: 'Basic' + btoa('xlz@wwe.com' + ":" + 'thepass')
            }
        })
        .then(function (response) {
            console.log(response);
        })
        .catch(function (error) {
            console.log(error);
        });

请参考下面的控制器代码:

package com.travelplanner.rest.controller;
//COPY
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.UserDetailsManager;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.travelplanner.rest.entity.UserDetails;
import com.travelplanner.rest.entity.TravelPlans;
import com.travelplanner.rest.service.UserService;

@RestController
@RequestMapping("/api")
public class UserRestController {

    @Autowired
    private UserService userService;

    @Autowired
    private UserDetailsManager userDetailsManager;

    private PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

    private boolean doesUserExist(String username) {
        boolean exists = userDetailsManager.userExists(username);

        return exists;
    }

//  API to add user
    @PostMapping("/user/register")
    public UserDetails addUser(@RequestBody UserDetails userDetails) {
        if(!doesUserExist(userDetails.getEmail())) {
            String encodedPassword = passwordEncoder.encode(userDetails.getPassword());
            encodedPassword="{bcrypt}"+encodedPassword;
            List<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList("ROLE_USER");
            User user = new User(userDetails.getEmail(), encodedPassword, authorities);
            userDetailsManager.createUser(user);
            userDetails.setId(0);
            userService.saveUser(userDetails);
            return userDetails;
        }else {
            return null;
        }

    }

//  API to get user/login
    @PostMapping("/users/{email}")
    public UserDetails authUser(@PathVariable String email) {
        return userService.getUser(email);
    }

//  API to add travel plan
    @PostMapping("/users/travel-plan/{userId}")
    public TravelPlans addTravelPlan(@RequestBody TravelPlans travelPlan, @PathVariable int userId) {
        userService.saveTravelPlan(travelPlan, userId);
        return travelPlan;
    }

//  API to update travel plan
    @PutMapping("/users/travel-plan/{userId}")
    public TravelPlans updateTravelPlan(@RequestBody TravelPlans travelPlan, @PathVariable int userId) {
        userService.updateTravelPlan(travelPlan, userId);
        return travelPlan; 
    }

//  API to get travel plans
    @GetMapping("/users/travel-plan/{userId}")
    public List<TravelPlans> getTravelPlans(@PathVariable int userId) {
        return userService.getTravelPlans(userId);
    }

//  API to delete travel plan
    @DeleteMapping("/users/travel-plan/{planId}")
    public String deleteTravelPlan(@PathVariable int planId) {
        userService.deleteTravelPlan(planId);  
        return "Deleted the travel plan with id: " + planId;
    }
}

我尝试添加@CrossOrigin(origins="http://localhost8585"),还尝试将.cors().disable放在config.java中http路径的开头和结尾,但似乎没有任何效果。我仍然在控制台中收到上述消息。

有关congfig.java,请参考下面的颂歌:

package com.travelplanner.rest.config;

import java.beans.PropertyVetoException;
import java.util.Properties;
import java.util.logging.Logger;

import javax.sql.DataSource;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

import com.mchange.v2.c3p0.ComboPooledDataSource;

@Configuration
@EnableWebMvc
@EnableTransactionManagement
@ComponentScan("com.travelplanner.rest")
@PropertySource({ "classpath:persistence-mysql.properties" })
public class DemoAppConfig implements WebMvcConfigurer {

    @Autowired
    private Environment env;

    private Logger logger = Logger.getLogger(getClass().getName());

    @Bean
    public DataSource myDataSource() {

        // create connection pool
        ComboPooledDataSource myDataSource = new ComboPooledDataSource();

        // set the jdbc driver
        try {
            myDataSource.setDriverClass("com.mysql.jdbc.Driver");       
        }
        catch (PropertyVetoException exc) {
            throw new RuntimeException(exc);
        }

        // for sanity's sake, let's log url and user ... just to make sure we are reading the data
        logger.info("jdbc.url=" + env.getProperty("jdbc.url"));
        logger.info("jdbc.user=" + env.getProperty("jdbc.user"));

        // set database connection props
        myDataSource.setJdbcUrl(env.getProperty("jdbc.url"));
        myDataSource.setUser(env.getProperty("jdbc.user"));
        myDataSource.setPassword(env.getProperty("jdbc.password"));

        // set connection pool props
        myDataSource.setInitialPoolSize(getIntProperty("connection.pool.initialPoolSize"));
        myDataSource.setMinPoolSize(getIntProperty("connection.pool.minPoolSize"));
        myDataSource.setMaxPoolSize(getIntProperty("connection.pool.maxPoolSize"));     
        myDataSource.setMaxIdleTime(getIntProperty("connection.pool.maxIdleTime"));

        return myDataSource;
    }

    private Properties getHibernateProperties() {

        // set hibernate properties
        Properties props = new Properties();

        props.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
        props.setProperty("hibernate.show_sql", env.getProperty("hibernate.show_sql"));

        return props;               
    }


    // need a helper method 
    // read environment property and convert to int

    private int getIntProperty(String propName) {

        String propVal = env.getProperty(propName);

        // now convert to int
        int intPropVal = Integer.parseInt(propVal);

        return intPropVal;
    }   

    @Bean
    public LocalSessionFactoryBean sessionFactory(){

        // create session factorys
        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();

        // set the properties
        sessionFactory.setDataSource(myDataSource());
        sessionFactory.setPackagesToScan(env.getProperty("hibernate.packagesToScan"));
        sessionFactory.setHibernateProperties(getHibernateProperties());

        return sessionFactory;
    }

    @Bean
    @Autowired
    public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {

        // setup transaction manager based on session factory
        HibernateTransactionManager txManager = new HibernateTransactionManager();
        txManager.setSessionFactory(sessionFactory);

        return txManager;
    }

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**").allowedOrigins("*");;
    }

}

请帮助! 预先感谢。

1 个答案:

答案 0 :(得分:0)

它对我有用:

@Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**");
    }