主要用于定制化将数据库数据对接Security框架。
import com.example.springsecuritystudy4.entity.User;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
import java.util.List;
public class SecurityUser implements UserDetails {
private final User user;
private List<SimpleGrantedAuthority> authorityList;
public SecurityUser(User user) {
this.user = user;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorityList;
}
public void setAuthorityList(List<SimpleGrantedAuthority> authorityList) {
this.authorityList = authorityList;
}
@Override
public String getPassword() {
String pwd = user.getPassword();
user.setPassword(null);
return pwd;
}
@Override
public String getUsername() {
return user.getUsername();
}
/*代表账号是否已经过期(true账号没有过期,false账号已经过期)*/
@Override
public boolean isAccountNonExpired() {
return user.getAccountNoExpired().equals(1);
}
/*代表账号是否被锁定(true没有锁定,false锁定)*/
@Override
public boolean isAccountNonLocked() {
return user.getAccountNoLocked().equals(1);
}
/*代表凭证是否已经过期(true账号没有过期,false账号已经过期)*/
@Override
public boolean isCredentialsNonExpired() {
return user.getCredentialsNoExpired().equals(1);
}
/*代表账号是否可用*/
@Override
public boolean isEnabled() {
return true;
}
}
实现UserDetailService接口的作用主要就是定制化用户登录时的数据获取方式以及对比方式等。
import com.example.springsecuritystudy4.entity.User;
import com.example.springsecuritystudy4.service.RoleMenuService;
import com.example.springsecuritystudy4.service.UserService;
import com.example.springsecuritystudy4.vo.SecurityUser;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
@Service
public class SecurityUserDetailServiceImpl implements UserDetailsService {
@Resource
private UserService userService;
@Resource
private RoleMenuService roleMenuService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User byUserName = userService.getByUserName(username);
if(byUserName==null)
throw new UsernameNotFoundException("该用户不存在");
List<String> queryPermissionsByUserId = roleMenuService.queryPermissionsByUserId(byUserName.getUid());
SecurityUser securityUser = new SecurityUser(byUserName);
List<SimpleGrantedAuthority> authorityList = new ArrayList<>();
queryPermissionsByUserId.stream().forEach((value)-> authorityList.add(new SimpleGrantedAuthority(value)));
securityUser.setAuthorityList(authorityList);
return securityUser;
}
}
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Slf4j
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest()
.authenticated();
http.formLogin()
.loginPage("/toLogin") // 配置登录页面
.usernameParameter("uname") // 用户名参数
.passwordParameter("pwd") // 密码参数
.loginProcessingUrl("/login/doLogin") //单击登录后进入url
.failureForwardUrl("/toLogin") // 登录失败
.successForwardUrl("/toIndex") //登录成功
.permitAll(); //配置登录
http.logout().logoutSuccessUrl("/toLogin"); //配置退出成功登录页面
http.csrf().disable(); //关闭跨域请求保护
}
}
验证码生成工具可以使用hutool依赖库进行。
import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.CircleCaptcha;
import cn.hutool.captcha.generator.MathGenerator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Slf4j
@Controller
public class CaptchaController {
@GetMapping(value = "code/getCaptchaCode")
public void getCaptchaCode(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse) throws IOException {
//ShearCaptcha shearCaptcha = CaptchaUtil.createShearCaptcha(200, 100, 4, 5);
CircleCaptcha circleCaptcha = CaptchaUtil.createCircleCaptcha(200, 100, 4, 1000);
circleCaptcha.setGenerator(new MathGenerator());
String code = circleCaptcha.getCode();
log.info("生成的图片验证码为:{}",code);
//将验证码存储到session中
httpServletRequest.getSession().setAttribute("CAPTCHA CODE",code);
httpServletResponse.setContentType("image/png");
//将图片写到响应流里
ImageIO.write(circleCaptcha.getImage(),"PNG",httpServletResponse.getOutputStream());
}
}
写好验证码之后即可在WebSecurity实现配置类中将验证码接口放开:
import com.example.springsecuritystudy4.filter.ValidateCodeFilter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import javax.annotation.Resource;
@Slf4j
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.mvcMatchers("/code/getCaptchaCode") //将验证码接口放开
.permitAll()
.anyRequest()
.authenticated();
http.formLogin()
.loginPage("/toLogin") // 配置登录页面
.usernameParameter("uname") // 用户名参数
.passwordParameter("pwd") // 密码参数
.loginProcessingUrl("/login/doLogin") //单击登录后进入url
.failureForwardUrl("/toLogin") // 登录失败
.successForwardUrl("/toIndex") //登录成功
.permitAll(); //放开
http.logout().logoutSuccessUrl("/toLogin"); //配置退出成功登录页面
http.csrf().disable(); //关闭跨域请求保护
}
}