How to show text fields from a User object to anonymous users without "View User Profile" permission?
Conversely, how I can prevent anyone from getting to user/* pages?


Getting technical here, you wouldn't want to block all /user/*; otherwise, you wouldn't be able to /user/login or /user/logout and also you would still want admins to access those /user/{uid} pages.

If  you inspect core/modules/user/user.routing.yml you can see most of the user routes. But what you expect, the /user/{uid} is not defined here.

It's actually defined in UserRouteProvider.php as /user/{user}



You can easily find the route name by enabling WebProfiler module that comes with Devel and  going to /user/1



Now all you gotta do is override the route's access by giving it a role of administrator.  

mymodule/src/Routing/RouteSubscriber.php

namespace Drupal\mymodule\Routing;

use Drupal\Core\Routing\RouteSubscriberBase;
use Symfony\Component\Routing\RouteCollection;

/**
 * Listens to the dynamic route events.
 */
class RouteSubscriber extends RouteSubscriberBase {

  /**
   * {@inheritdoc}
   */
  protected function alterRoutes(RouteCollection $collection) {
    // Allow only admins to access '/user/{user}'.
    if ($route = $collection-&gt;get('entity.user.canonical')) {
        $route-&gt;setRequirement('_role', 'administrator');
    }
  }

}


Alternatively, in your custom module, you could create a new permission and use that for the Route's setRequirement instead and then assign the new permission to the roles that you want to have access.

mymodule/example.services.yml

services:
  mymodule.route_subscriber:
    class: Drupal\mymodule\Routing\RouteSubscriber
    tags:
      - { name: event_subscriber }


For more in depth information about altering routes, see: Altering existing routes and adding new routes based on dynamic ones.