我试图在后端实现身份验证弹簧启动,在前端实现vue Js,问题是我已经将backkend只读连接到数据库,因此使用了vue js和firebase authentication功能进行身份验证。
如果有人有解决办法,请继续,谢谢!
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>
例如,这是我回购的一部分,并且有事件列表:
@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;
}
答案 0 :(得分:2)
这是正常行为,因为您使用管理员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;
}
}
然后您需要启用网络安全性:
WebSecurityConfig.java
@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);
}
}
最后,您添加了一个请求过滤器,该过滤器每次对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");
}
}
现在,您的API端点已保存,可以防止未经授权的请求。
在Web应用程序中,您通常使用firebase处理授权。在对spring-boot应用程序的每个请求中,您都将访问令牌作为Authorization
标头传递。
请记住,这并不是真正的节省,因为spring boot API充当firebase SDK的管理员。