使用 firebase 进行 Spring Boot 和 vueJs 身份验证

Edw*_*vin 4 rest firebase spring-boot vue.js firebase-authentication

我正在尝试在后端实现身份验证 spring boot 并在前端实现 vue Js,问题是我的后端以只读方式连接到数据库,因此使用了使用 vue js 和firebase 身份验证功能的身份验证

问题是我的端点仍然可以访问,任何人都可以使用邮递员发送请求和获取数据

如果有人知道如何解决这个问题,请继续,谢谢!

PS:我不认为我可以提供帮助,但无论如何这是我的登录代码,@Renaud Tarnec

import firebase from 'firebase'

export default {
  name: 'login',
  data: function() {
    return {
      email: '',
      password: ''
    }
  },
  methods: {
    signIn: function() {
      firebase.auth().signInWithEmailAndPassword(this.email, this.password).then(
        function(user) {
          alert('You are connected')
        },
        function(err) {
          aler('Ooops,' + err.message)
        }
      );
    }
  }
}
</script>
Run Code Online (Sandbox Code Playgroud)

这是例如我的回购的一部分,并且有事件列表:

@RequestMapping("api/events")
public class EventController {
    @Autowired
    private EventRepository eventrepository;

    @GetMapping
    public ArrayList<Event> find() {
        ArrayList<Event> events = new ArrayList<Event>();
        for (Event e : eventrepository.findAll()) {
            System.out.println(e);
            events.add(e);
        }
        return events;
    }
Run Code Online (Sandbox Code Playgroud)

Ker*_*ten 8

这是正常行为,因为您使用 admin sdk 凭据向 firestore 发送请求。

您需要将一些身份验证放入您的 Spring Boot 应用程序中。

我将一些代码放在一起,将您的所有请求置于 firebase 身份验证之后。

FirebaseConfig.java

@Configuration
@EnableConfigurationProperties
@ConfigurationProperties(prefix="firebase")
public class FirebaseConfig {

    private static final Logger logger = LoggerFactory.getLogger(FirebaseConfig.class);

    private String databaseURL;
    private String serviceAccount;

    @Bean
    public DatabaseReference firebaseDatabse() {
        DatabaseReference firebase = FirebaseDatabase.getInstance().getReference();
        return firebase;
    }

    @PostConstruct
    public void init() {

        try {
            FirebaseApp.getInstance();
        } catch (IllegalStateException e) {
            try {
                InputStream inputStream = FirebaseConfig.class.getClassLoader().getResourceAsStream(serviceAccount);

                try {
                    FirebaseOptions options = new FirebaseOptions.Builder().setCredentials(GoogleCredentials.fromStream(inputStream))
                            .setDatabaseUrl(databaseURL).build();

                    FirebaseApp.initializeApp(options);
                } catch (IOException ioE) {
                    ioE.printStackTrace();
                }
            } catch (NullPointerException nullE) {
                nullE.printStackTrace();
            }
        }

    }

    public String getDatabaseURL() {
        return databaseURL;
    }

    public void setDatabaseURL(String databaseURL) {
        this.databaseURL = databaseURL;
    }

    public String getServiceAccount() {
        return serviceAccount;
    }

    public void setServiceAccount(String serviceAccount) {
        this.serviceAccount = serviceAccount;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你需要启用网络安全:

网络安全配置文件

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    private static final Logger logger = LoggerFactory.getLogger(WebSecurityConfiguration.class);

    /**
     * Use to create instance of {@link FirebaseAuthenticationTokenFilter}.
     *
     * @return instance of {@link FirebaseAuthenticationTokenFilter}
     */
    public FirebaseAuthenticationTokenFilter firebaseAuthenticationFilterBean() throws Exception {
        logger.debug(
                "firebaseAuthenticationFilterBean():: creating instance of FirebaseAuthenticationFilter.");

        FirebaseAuthenticationTokenFilter authenticationTokenFilter = new FirebaseAuthenticationTokenFilter();

        return authenticationTokenFilter;
    }

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {

        httpSecurity
                .cors()
                .and()
                .csrf()
                .disable()
                .authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        // Custom security filter
        httpSecurity.addFilterBefore(firebaseAuthenticationFilterBean(),
                UsernamePasswordAuthenticationFilter.class);
    }

}
Run Code Online (Sandbox Code Playgroud)

最后,您添加一个请求过滤器,用于在您每次针对 api 发出请求时验证访问令牌。

FirebaseAuthenticationTokenFilter.java

@Component
public class FirebaseAuthenticationTokenFilter extends OncePerRequestFilter {

    private static final Logger logger = LoggerFactory.getLogger(FirebaseAuthenticationTokenFilter.class);
    private final static String TOKEN_HEADER = "Authorization";

    /**
     *
     * @param request
     * @param response
     * @param filterChain
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        logger.debug("doFilter:: authenticating...");

        HttpServletRequest httpRequest = request;
        String authToken = httpRequest.getHeader(TOKEN_HEADER);

        if (Strings.isNullOrEmpty(authToken)) {
            filterChain.doFilter(request, response);
            return;
        }

        try {
            Authentication authentication = getAndValidateAuthentication(authToken);
            SecurityContextHolder.getContext().setAuthentication(authentication);
            logger.debug("doFilter():: successfully authenticated.");
        } catch (Exception ex) {
            HttpServletResponse httpResponse = response;
            httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            logger.debug("Fail to authenticate.", ex);
        }

        filterChain.doFilter(request, response);
    }

    /**
     *
     * @param authToken Firebase access token string
     * @return the computed result
     * @throws Exception
     */
    private Authentication getAndValidateAuthentication(String authToken) throws Exception {
        Authentication authentication;

        FirebaseToken firebaseToken = authenticateFirebaseToken(authToken);
        authentication = new UsernamePasswordAuthenticationToken(firebaseToken, authToken, new ArrayList<>());

        return authentication;
    }

    /**
     * @param authToken Firebase access token string
     * @return the computed result
     * @throws Exception
     */
    private FirebaseToken authenticateFirebaseToken(String authToken) throws Exception {
        ApiFuture<FirebaseToken> app = FirebaseAuth.getInstance().verifyIdTokenAsync(authToken);

        return app.get();
    }

    @Override
    public void destroy() {
        logger.debug("destroy():: invoke");
    }

}
Run Code Online (Sandbox Code Playgroud)

现在,您的 API 端点可以防止未经授权的请求。

在您的 Web 应用程序中,您可以像平常一样使用 firebase 处理授权。在对 spring-boot 应用程序的每个请求中,您都将访问令牌作为Authorization标头传递。

请记住,这并不是真正的保存,因为 spring boot API 充当针对 firebase SDK 的管理员。