springboot 集成 springsecutity 前后端分离使用token

网上很多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的问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值