Good morning, the most viable, reliable and appropriate solution in your case I believe would be to work with the 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 annotation @EnableWebSecurity
You will need to configure users to within the spring context, you can configure them inMemory
if using only some entry points restriction 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 the UserDetailsService
follows an example with jpa
(but you can work with any database):
Your user 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>{
}
Implementation of the 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 you will use, basically it allows you to make various settings, I will leave an example of configuration using X509 (private and public key)protection against attack xss and disabling the csrf action token (validation of actions allowed to the user). spring-security exists a universe of settings that you can use or customize, suggested 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 settings SecurityConfiguration
, if you used the UserDetailsService
will need to inject the implementation of UserDetailsService
and implement the method configureGlobal
in this way:
Settings Userdetailsservice
@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 the configureGlobal
in this way:
Configuration inMemory
@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 kind of encryption (highly recommended), need to inject the BCryptPasswordEncoder
:
Cryptography
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
also change the settings to
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}
remembering that with the encryption enabled you must save in the bank or inMemory the password of already encrypted users.
Hi Matheus, if you really need authentication / authorization I would take a look at Spring Security, creating a single user for the system. But this kind of problem back and forth can be solved in another layer. E.g., system services may be hidden from the end user (system topology).
– Anthony Accioly
@Matheus Have you considered the possibility of using token?
– DiegoAugusto
@Type where I pass the header?
– Matheus
@Matheus Yes, but you would use a library to do this. In my case I use JWT, but as mentioned above you can use Spring Security
– DiegoAugusto
@Diegoaugusto I will take a look at this library. Vlw.
– Matheus