Hamilton qualified in second and fell to third early in the race as Verstappen raced past him coming out of a safety car situation.
But the defending champion's skill and speed came to the fore as he outmaneuvered the two men ahead of him.
Hamilton also reeled in Sergio Perez, who had stayed out on his tyres in a desperate attempt to hold up the 2021 Formula 1® leader.
A comfortable margin of victory gave Hamilton a second win of the season, having finished second in the other race, but he was keen to emphasise the difficulty of the task.
The Mercedes superstar, while acknowledging "today wasn't all perfect", said: "That was such a tough race, physically and mentally, just keeping everything together.
"It was very windy out there, obviously, so it was very easy to put a foot wrong.
"I didn't quite get as good a start as Valtteri and then lost out on the restart, which I was not happy about, naturally. I really had to try to position myself the best I could.
"I think Max made a mistake at some point through the lap, which was perfect. I knew that was going to be the lap I was going to get as close as I could to him in the last sector.
"With Valtteri, I had to make the move early on before the tyres were destroyed. I managed to just get him at Turn One, just where I wanted him. It was a great race."
Verstappen had bemoaned the tricky conditions after qualifying, saying the Portuguese Grand Prix had "not been a lot of fun to drive".
"Hopefully everything stabilises," he added on Saturday, but Turn 14 continued to test the Red Bull, errors at that corner letting Hamilton in and later denying the Dutchman the fastest lap as he ran wide.
"I think this was a bit of an odd weekend in terms of grip," Verstappen said. "We were not on top of it, but we'll see what we can do in Barcelona."
Bottas, who profited to claim the fastest lap but finished third, was not happy either.
"It was a little tricky day today," the Finn said. "I don't know what happened in the first stint, I just didn't have the pace for unknown reasons.
"I need to have a look at that. The second stint was pretty good but there was an issue with some sensor or something."