Repository: PrefectHQ/prefect

Issue:
403 error in UI after upgrading to 2.16.6
### First check

- [X] I added a descriptive title to this issue.
- [X] I used the GitHub search to find a similar issue and didn't find it.
- [X] I refreshed the page and this issue still occurred.
- [X] I checked if this issue was specific to the browser I was using by testing with a different browser.

### Bug summary

After upgrading from prefect 2.14.something to 2.16.6 :
- I first notice that UI was empty : no flow runs, no blocks, etc... No error message is provided 
- i then see that browser was receiving 403 response in POST request. Response for that request was "{"detail":"Missing CSRF token."}"
- emptying browser's cache was not a solution
- I noticed that upgrading prefect (with a simple pip -U prefect) does not upgrade the ui_build directory located in prefect's package path. I understand that this directory contains assets used in the UI

So as a workaround, I delete the ui_build directory, restart prefect server, clear cache and it was good.

Do you consider that behaviour as an expected behaviour ? How can I make prefect upgrade safer ?

### Reproduction

On a fresh virtual env :
```
pip install prefect==2.16.4
prefect server start
```
(stop server)
```
pip install -U prefect
prefect server start
```
Launch a web server and check network requests -> 403 response

### Error

"{"detail":"Missing CSRF token."}" in all post response in UI

### Browsers

- [X] Chrome
- [X] Firefox
- [ ] Safari
- [ ] Edge

### Prefect version

```Text
Version:             2.16.6
API version:         0.8.4
Python version:      3.10.12
Git commit:          3fecd435
Built:               Sat, Mar 23, 2024 4:06 PM
OS/Arch:             linux/x86_64
Profile:             default
Server type:         ephemeral
Server:
  Database:          sqlite
  SQLite version:    3.37.2
```


### Additional context

_No response_


Discussion:

Resolving patch:
diff --git a/src/prefect/server/api/server.py b/src/prefect/server/api/server.py
--- a/src/prefect/server/api/server.py
+++ b/src/prefect/server/api/server.py
@@ -338,6 +338,7 @@ async def orion_info():
 def create_ui_app(ephemeral: bool) -> FastAPI:
     ui_app = FastAPI(title=UI_TITLE)
     base_url = prefect.settings.PREFECT_UI_SERVE_BASE.value()
+    cache_key = f"{prefect.__version__}:{base_url}"
     stripped_base_url = base_url.rstrip("/")
     static_dir = (
         prefect.settings.PREFECT_UI_STATIC_DIRECTORY.value()
@@ -363,7 +364,7 @@ def reference_file_matches_base_url():
         if os.path.exists(static_dir):
             try:
                 with open(reference_file_path, "r") as f:
-                    return f.read() == base_url
+                    return f.read() == cache_key
             except FileNotFoundError:
                 return False
         else:
@@ -384,7 +385,7 @@ def create_ui_static_subpath():
         # This is used to determine if the static files need to be copied again
         # when the server is restarted
         with open(os.path.join(static_dir, reference_file_name), "w") as f:
-            f.write(base_url)
+            f.write(cache_key)
 
     ui_app.add_middleware(GZipMiddleware)
 


Test patch: