网上很多demo,我也记录一下,不过有的功能还没实现..仅做记录
1.创建用户信息的实体类,可随意扩展其他属性变量
public class UserInfo implements UserDetails {
private Long id;
private String userName;
private String password;
private List<String> roles; //用户角色
public List<String> getRoles() {
return roles;
}
public void setRoles(List<String> roles) {
this.roles = roles;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public void setPassword(String password) {
this.password = password;
}
//这里遍历用户角色赋值到集合里
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
Set list = new HashSet();
if (roles != null && roles.size() != 0) {
for (String role : roles) {
list.add(new SimpleGrantedAuthority(role));
}
}
return list;
}
@Override
public String getPassword() {
return password;
}
@Override
public String getUsername() {
return 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;
}
}
2.制造了点假数据
public class Constant {
public static class getMap {
private static Map map;
public static Map get() {
if (map == null) {
map = new HashMap();
}
map.put("gao", new UserInfo() {{
setId(1L);
setPassword(new BCryptPasswordEncoder().encode("123"));
setUserName("gao");
List list = new ArrayList<>();
list.add("ROLE_admin");
setRoles(list);
}});
map.put("yang", new UserInfo() {
{
setId(2L);
setPassword(new BCryptPasswordEncoder().encode("321"));
setUserName("yang");
List list = new ArrayList<>();
list.add("guest");
setRoles(list);
}
});
return map;
}
}
}
3.自定义拦截
@Component
public class MyFilter extends OncePerRequestFilter {
//注入用户验证类
@Autowired
private MyUserDetailService myUserDetailService;
@Override
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
//取出前端传来的验证token
String token = httpServletRequest.getHeader("token");
//如果token为空或者已有登陆信息则进行重复登陆
if (token != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = myUserDetailService.loadUserByUsername(token);
if (userDetails != null) {
Collection<? extends GrantedAuthority> authorities = userDetails.getAuthorities();
UsernamePasswordAuthenticationToken us = new UsernamePasswordAuthenticationToken(userDetails, null, authorities);
us.setDetails(new WebAuthenticationDetails(httpServletRequest));
SecurityContextHolder.getContext().setAuthentication(us);
}
}
//这里登陆成功后,可以更新jwt过期时间,通过header返回给前端
filterChain.doFilter(httpServletRequest, httpServletResponse);
}
}
4.验证登陆信息
@Component
public class MyUserDetailService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException {
//模拟数据库查询用户
//此处可使用jwt进行验证,如有错误则抛出多少错误
Map map = Constant.getMap.get();
UserInfo user = (UserInfo) map.get(name);
if (user == null) {
throw new UsernameNotFoundException("用户名不存在");
}
return user;
}
}
5.权限中心
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true) //开启注解
public class SecutityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private MyFilter myFilter;
@Autowired
private NotLogin notLogin;
@Bean
public UserDetailsService userDetailsService() {
return new MyUserDetailService();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
//设置验证方法及加密方式
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService()).passwordEncoder(new BCryptPasswordEncoder());
}
@Autowired
private DeniedHandler deniedHandler;
@Autowired
private LoginSuccesssHandler loginSuccesssHandler;
@Autowired
private LoginFailHandler loginFailHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.httpBasic().authenticationEntryPoint(notLogin)
.and()
.formLogin() //表单登陆后的回调,这里用不到,没有通过表单登陆验证
.successHandler(loginSuccesssHandler)
.failureHandler(loginFailHandler)
.permitAll()
.and() //自定义登陆方式
.authorizeRequests()
.antMatchers("/open")
.permitAll()
.antMatchers("/index")
.access("hasRole('admin')")
.and()
.authorizeRequests()
.anyRequest()
.authenticated();
http.exceptionHandling().accessDeniedHandler(deniedHandler);
http.addFilterBefore(myFilter, UsernamePasswordAuthenticationFilter.class);
}
}
6.一些自定义的回调
@Component
public class NotLogin implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
httpServletResponse.setContentType("text/html;charset=utf-8");
httpServletResponse.getWriter().write("未登录");
}
}
@Component
public class DeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
httpServletResponse.getWriter().write(" denied");
}
}
@Component
public class LoginFailHandler implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
httpServletResponse.getWriter().write("login fail");
}
}
@Component
public class LoginSuccesssHandler implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
httpServletResponse.getWriter().write("login success");
}
}
7.controller
@RestController
public class web {
//这里可以生成jwt的token
@GetMapping("/my_login")
public Object my_login(String user,String password){
if()xxxxxx
return "jwt_token";
}
@GetMapping("/index")
public Object index(){
return "测试";
}
@GetMapping("/login/error")
public Object error(){
return "登陆失败";
}
@GetMapping("/open")
public Object open(){
return "测试开放接口";
}
}
写的很简陋.很多功能没有实现,其中碰到的坑;关于role的问题