Apex classes currently do not apply profile or permission set constraints - so the "CRUD" (Create, Read, Update, Delete) and "FLS" (Field Level Security) aspects of security are not applied. Thus, a user without permission to access Accounts at all can still run Apex code that queries a bunch of Account instances and returns some data to the UI.
On the other hand, Apex classes will apply Sharing Rules, thereby filtering out instances from the results of SOQL or SOSL queries based on those rules, when they are declared "with sharing" or when inheriting sharing from the caller.
Note that the use of standard "field" handling components in pages (be that Visualforce or Lightning) for presenting input or output fields WILL actually apply CRUD and FLS, so for example if the user has no access to the Account's Name, an attempt to provide an input for the name using a standard "field" handling component could actually either show the name as read-only or hide it altogether, depending on the CRUD/FLS for that field for the given user.
On the other hand, if you write your own components or use (standard or third party) components that are not for field handling, you have to deal with the CRUD/FLS aspects for yourself.