Good morning, the most feasible, reliable and appropriate solution in your case I believe it would work with spring-security
:
pom
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
To enable spring-secutiry you will need the @EnableWebSecurity
You will need to configure the users into the spring context, you can set them inMemory
if you only use the restriction to some entry points for the system, or fixed users:
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
auth.inMemoryAuthentication()
//Caso o usuario de sistema pode ser tbm adm, mais se preferir pode deixar apenas System
.withUser("UsuarioSistema").password("SenhaUsuarioSistema").roles("SYSTEM", "ADMIN").and()
//Não é obrigatório
.withUser("usuario1").password("senha1").roles("USER");
}
Or work with an implementation of UserDetailsService
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
To work with UserDetailsService
follow an example with jpa
(but you can work with any database):
Your users table
@Entity
@Table(name = "user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String username;
private String password;
@ManyToMany
@JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<Role> roles;
//Gets e Sets
}
Your Permissions table
@Entity
@Table(name = "role")
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
@ManyToMany(mappedBy = "roles")
private Set<User> users;
//Gets e Sets
}
Repository Interface for the User
public interface UserRepository extends JpaRepository<User, Long> {
User findByUsername(String username);
}
Repository interface for permissions
public interface RoleRepository extends JpaRepository<Role, Long>{
}
Deployment of UserDetailsService
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
@Transactional(readOnly = true)
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
for (Role role : user.getRoles()) {
grantedAuthorities.add(new SimpleGrantedAuthority(role.getName()));
}
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(),
grantedAuthorities);
}
}
Finally the last step, you will need to configure the security standards that you will use, basically it allows you to make several configurations, I will leave an example configuration using x509 (private key and publish), protection against xss attack and disabling token of csrf actions (validation of actions allowed to the user). Spring-security has a universe of settings you can use or customize, suggestion of links spring docs , algaworks and devmedia
General configuration of spring-security
//Classe de configuração geral do spring-security
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
//Padrões de configuração de seu sistema
@Override
protected void configure(HttpSecurity http) throws Exception {
//Autorização para requisições
http.authorizeRequests()
//Permite acesso de todos para / para frente
.antMatchers("/**")
.permitAll().and()
//Permite acesso apenas de usuarios System para /meuEndPoint/ para frente
.antMatcher("/meuEndPoint/**")
.authorizeRequests()
.anyRequest().hasRole("SYSTEM")
.anyRequest().authenticated()
.and().httpBasic();
//Configurações
http.x509().and()
.headers().xssProtection().and().and()
.csrf().disable();
}
}
Still within the SecurityConfiguration
settings, if you used UserDetailsService
you will need to inject the UserDetailsService
implementation and implement the configureGlobal
method like this:
UserDetailsService Configuration
@Autowired
private UserDetailsService userDetailsService;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}
If you have used the inMemory user you will need to implement configureGlobal
this way:
InMemory Configuration
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
auth.inMemoryAuthentication()
.withUser("UsuarioSistema").password("SenhaUsuarioSistema").roles("SYSTEM", "ADMIN").and()
.withUser("usuario1").password("senha1").roles("USER");
}
Another important point, if you want to use some type of encryption (highly recommended), you need to inject BCryptPasswordEncoder
:
Encryption
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
In addition to this change the configureGlobal to
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}
Remembering that with encryption enabled you should save in the bank or inMemory the password of users already encrypted.