前言
Spring Security,这是一种基于 Spring AOP 和 Servlet 过滤器的安全框架。它提供全面的安全性解决方案,同时在 Web 请求级和方法调用级处理身份确认和授权。其自身拥有一套管理用户登录信息的方法,本文就将介绍简单的使用Spring Security 来实现用户登录。
框架介绍
本文将使用Spring boot + Spring Security实现,Spring boot相对于Spring使用起来比较简单,提供了很多默认的设置,力求开箱即用。Spring boot版本采用1.5.6 RELEASE,Spring Security 版本与其一致。
pom文件:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
功能实现
首先进行Spring Security 的配置:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true) //开启security注解
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
@Override
protected AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
@Override
public void configure(WebSecurity web) throws Exception {
//解决静态资源被拦截的问题
web.ignoring().antMatchers("/somewhere/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
//允许所有用户访问"/"和"/home"
http.authorizeRequests()
.antMatchers("/", "/home").permitAll()
//其他地址的访问均需验证权限
.anyRequest().authenticated()
.and()
.formLogin()
//指定登录页是"/login"
.loginPage("/login")
//登录成功后默认跳转到
.defaultSuccessUrl("/welcome")
.permitAll()
.and()
.logout()
.logoutUrl("/logout")
//退出登录后的默认url是"/login"
.logoutSuccessUrl("/login")
.permitAll();
//解决非thymeleaf的form表单提交被拦截问题
http.csrf().disable();
//解决中文乱码问题
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("UTF-8");
filter.setForceEncoding(true);
http.addFilterBefore(filter,CsrfFilter.class);
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(systemUserService()).passwordEncoder(passwordEncoder());
//也可以将用户名密码写在内存,不推荐
auth.inMemoryAuthentication().withUser("admin").password("111111").roles("USER");
}
/**
* 设置用户密码的加密方式为MD5加密
*/
@Bean
public Md5PasswordEncoder passwordEncoder() {
return new Md5PasswordEncoder();
}
/**
*从数据库中读取用户信息
*/
@Bean
public UserDetailsService systemUserService() {
return new UserService();
}
}
上面为Spring boot 中 Spring Security 的配置,其中configureGlobal()方法为校验用户名密码的方法,此处使用了密码进行MD5加密的方式,即用户输入的密码进行加密后与数据库中存储的密码进行对比,数据库中的密码也要采用一致的加密方式,当然也可以采用其他的加密方式,Spring Security 也提供了响应的方法,此处不再举例。
UserService.java
public class UserService implements UserDetailsService {
@Autowired
private SystemUserService systemUserService;
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
//根据用户名从数据库查询对应记录
SystemUser systemUser = systemUserService.queryByUserName(s);
if (systemUser == null) {
throw new UsernameNotFoundException("username is not exists");
}
System.out.println("username is : " + systemUser.getUsername() + ", password is :" + systemUser.getPassword());
return systemUser;
}
}
SystemUserService.java
@Component
public class SystemUserService {
@Autowired
private SystemUserMapper systemUserMapper;
public SystemUser queryByUserName(String username) {
return systemUserMapper.queryByUserName(username);
}
}
上面的逻辑非常简单,从数据库中根据用户名查询对应的记录,返回对应的实体对象,此处实体对象与普通的实体有一定的区别,来看一下
SystemUser.java
@Table(name = "system_user")
public class SystemUser implements UserDetails {
@Id
@GeneratedValue(generator = "JDBC")
private Integer id;
private String username;
private String password;
private Date createTime;
public Integer getId() {
return id;
}
public Date getCreateTime() {
return createTime;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<GrantedAuthority> auths = new ArrayList<>();
auths.add(new SimpleGrantedAuthority("USER"));
return auths;
}
@Override
public String getUsername() {
return username;
}
@Override
public String getPassword() {
return password;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
public void setId(Integer id) {
this.id = id;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
}
实体对象需要实现来自于Spring Security 的UserDetails这个接口,并实现其方法,其中getAuthorities()方法是控制当前用户的角色信息,可以根据需要进行配置,此处只是简单的进行了配置。
结束
上述就是Spring boot + Spring Security 来实现简单用户登录管理,数据库表的信息并未展示,可以根据具体需要进行设定,注意的是username与password两个字段必须存在。
同时如果选择了加密方式,需要确保存储时数据库中的数据的加密方式与配置的加密方式是一致的,否则会出现密码无法校验通过的问题。