Spring security是一个安全框架,此处不作赘述。本文只写如何使用Spring security,以及在搭建中遇到的问题。
maven依赖:
org.springframework.boot
spring-boot-starter-security
mvc入口页面配置文件:
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("login").setViewName("login");
}
}
安全配置文件:
import com.kindo.vine.example.service.CustomUserService;
import com.kindo.vine.utils.MD5Util;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
//登录需要用到的Service,必须注册这个
@Bean
UserDetailsService customUserService() {
return new CustomUserService();
}
//配置用户登录以及密码
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(customUserService()).passwordEncoder(new PasswordEncoder() {
@Override
public String encode(CharSequence rawPassword) {
return MD5Util.encode((String) rawPassword);
}
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
//其中encodepassword是数据库中的密码
return encodedPassword.equals(MD5Util.encode((String) rawPassword));
}
});
}
//过滤器
//以下都是不需要权限或者安全的
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/templates/**");
web.ignoring().antMatchers("/example/**");
web.ignoring().antMatchers("/static/**");
web.ignoring().antMatchers("/swagger-ui.html");
web.ignoring().antMatchers("/favicon.ico");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// 强制登录login
// http.sessionManagement().invalidSessionUrl("/login").maximumSessions(1).expiredUrl("/login");
http.authorizeRequests().antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/kindo").hasAnyRole("ADMIN", "OTHER");
// .antMatchers("/kindo").hasAuthority("");
http.authorizeRequests()
// .anyRequest().authenticated()//表示其他的请求都必须要有安全验证
.and().formLogin().loginPage("/login").failureUrl("/login?error").permitAll()
// .and()
// //开启cookie保存用户数据
// .rememberMe()
// //设置cookie有效期
// .tokenValiditySeconds(60 * 60 * 24 * 7)
.and().logout().permitAll();
http.csrf().disable(); //此处为禁用CSRF,默认开启CSRF
// http.headers().xssProtection();//XSS 保护
}
}
登录的CustomUserService ,该Service必须实现UserDetailsService :
import com.kindo.vine.example.entity.vineDo.VineUser;
import com.kindo.vine.example.entity.vineVo.UserInfo;
import com.kindo.vine.example.repository.read.SysUserReadRepsitory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
public class CustomUserService implements UserDetailsService {
Logger logger = LoggerFactory.getLogger(CustomUserService.class);
@Autowired
private SysUserReadRepsitory sysUserRepsitory;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
VineUser user = sysUserRepsitory.findByUsername(username);
//DO转DTO
UserInfo userInfo =user.toUserInfo();
if (null == userInfo) {
throw new UsernameNotFoundException("用户名不存在!");
}
System.out.println("登录人的用户名:" + userInfo.getUsername() + "、密码:" + userInfo.getPassword());
return userInfo;
}
}
最后输出的对象 UserInfo 必须继承 UserDetails,并重写某些方法 :
import com.kindo.vine.example.entity.vineDo.VineRole;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
/**
* Created by lingbao on 2017/10/26.
*
* @author lingbao
* @Description
* @Modify
*/
public class UserInfo implements UserDetails {
private Long id;
private String username;
private String password;
private Set roles;//角色集合
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
public Set getRoles() {
return roles;
}
public void setRoles(Set roles) {
this.roles = roles;
}
@Override
public Collection extends GrantedAuthority> getAuthorities() {
List auths = new ArrayList<>();
System.out.println("用户名为:"+this.getUsername()+",拥有的角色权限为:");
for (VineRole role:this.getRoles()) {
auths.add(new SimpleGrantedAuthority(role.getRole2()));
System.out.print(role.getRole2()+"\t");
}
System.out.println("");
return auths;
}
@Override
public String getPassword() {
return this.password;
}
@Override
public String getUsername() {
return this.username;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}