编写实现类实现UserDetailsService接口的loadUserByUsername方法
自定义从数据库查询用户密码和权限等信息
@Service
public class UserDetailServiceImpl implements UserDetailsService {
@Autowired
SysUserMapper userMapper;
@Autowired
SysMenuMapper menuMapper;
/**
* 自定义loadUserByUsername
* 从数据库获取用户的密码和权限
* @param username
* @return
* @throws UsernameNotFoundException
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
QueryWrapper<SysUser> wrapper=new QueryWrapper<>();
wrapper.eq("username",username);
//查询用户
SysUser user=userMapper.selectOne(wrapper);
if(user==null){
throw new UsernameNotFoundException("用户不存在");
}
//查询用户的权限
List<String> permTags=menuMapper.selectPermTagByUserId(user.getId());
List<GrantedAuthority> auths= AuthorityUtils.createAuthorityList(permTags.toArray(new String[0]));
return new User(username, user.getPassword(), auths);
}
}
配置密码器以及权限放行以及跨域和csrf拦截等
@Configuration
@EnableWebSecurity
//启用@PreAuthorize注解
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
UserDetailsService userDetailsService;
/**
* 配置Pbkdf2密码器
* @param auth
* @throws Exception
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(new Pbkdf2PasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
//使用自定义表单登录
http.formLogin()
//未登录返回json
.loginPage("/unLogin")
//登录url
.loginProcessingUrl("/login")
//登录成功,返回json
.successHandler((request, response, authentication) -> {
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter();
AxiosResult axiosResult=new AxiosResult(200,"登陆成功",authentication.getPrincipal());
out.println(new ObjectMapper().writeValueAsString(axiosResult));
out.flush();
out.close();
})
//登录失败,返回json
.failureHandler((request, response, ex) -> {
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter();
AxiosResult axiosResult=new AxiosResult(401);
if (ex instanceof UsernameNotFoundException || ex instanceof BadCredentialsException) {
axiosResult.setMessage("用户名或密码错误");
} else if (ex instanceof DisabledException) {
axiosResult.setMessage("账户被禁用");
} else {
axiosResult.setMessage("登录失败");
}
out.println(new ObjectMapper().writeValueAsString(axiosResult));
out.flush();
out.close();
})
//没有权限拒绝访问,返回json
.and().exceptionHandling().accessDeniedHandler((request, response, accessDeniedException)->{
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter();
AxiosResult axiosResult=new AxiosResult(403,"拒绝访问");
out.println(new ObjectMapper().writeValueAsString(axiosResult));
out.flush();
out.close();
})
//退出登录url
.and().logout().logoutUrl("/logout")
//退出成功,返回json
.logoutSuccessHandler((request, response, authentication) -> {
response.setContentType("application/json;charset=utf-8");
AxiosResult axiosResult=new AxiosResult(200,"退出登录成功");
PrintWriter out = response.getWriter();
out.println(new ObjectMapper().writeValueAsString(axiosResult));
out.flush();
out.close();
})
//授权配置
.and().authorizeRequests()
//所有请求
.anyRequest()
//都放行
.permitAll()
//授权配置
//.and().authorizeRequests()
//.antMatchers("/picture/pictures").hasAuthority("pictures")
//开启跨域访问
//.and().cors()
//关闭csrf拦截(开启会拦截postman)
.and().csrf().disable();
}
}
@RestController
public class LoginController {
@Autowired
ISysUserService sysUserService;
@GetMapping("/unLogin")
public AxiosResult unLogin(){
return new AxiosResult(401,"未登录");
}
@PostMapping("/register")
public AxiosResult register(@RequestBody SysUser user){
//把明文编码成密文
String pwd= new Pbkdf2PasswordEncoder().encode(user.getPassword());
user.setPassword(pwd);
if(sysUserService.save(user)){
return new AxiosResult(200,"注册成功");
}
return new AxiosResult(500,"注册失败");
}
}
使用@PreAuthorize注解控制权限,标在类上代表该controller中所有接口都需要’picture’权限,如果标在方法上只作用于当前方法
@RestController
@PreAuthorize("hasAuthority('picture')")
@RequestMapping("/picture")
public class PictureController {
@Autowired
IPictureService pictureService;
@PostMapping("/storage")
public int storage(@RequestBody MultipartFile file) throws IOException {
//图片名
String filename=file.getOriginalFilename();
//图片二进制数据
byte[] binaryData = file.getBytes();
//压缩
byte[] thumbnail=null;
if(filename!=null){
File f=new File(filename);
Thumbnails.of(file.getInputStream()).scale(0.2f).toFile(f);
InputStream is=new FileInputStream(f);
thumbnail=is.readAllBytes();
}
return pictureService.storage(filename,binaryData,thumbnail);
}
}