Usually hard limits on angular displacements are specified as constraints which are handed off to your dynamics engine which will (hopefully) use some computational magic to come up with a set of impulses that when applied to your rigid bodies will satisfy all the specified constraints simultaneously. That's the general approach anyway. It's a complex solution that's difficult to implement but it is very robust.
Perhaps you don't need that level of sophistication though. An easy solution is to detect when the constraint is violated and simply compute a corrective impulse in isolation such that the angular velocity is instantaneously changed and the constraint is not violated further. The angular displacement is likely to drift and violate the constraint even with the corrective impulse; you'll need to project it back into the valid space as well.
If rotation about x and y is prohibited and rotation about z is limited to +45 to -45 then a really simple way of enforcing this would be...
1) Convert the orientation quaterion to an axis and angle pair (v, theta)
2) Set v.x and v.y to zero and clamp theta to [-45, 45]
3) Convert the adjusted (v, theta) back into a quaternion and use this for the final orientation.
4) Set the x and y component of your angular velocity to zero. If theta was previously found to be outside of the [-45, 45] limit in step 2 then set the z component of the angular velocity to zero as well.
This is super naïve, especially steps 1, 2 and 3 but it should work.