Spring Security自定义登录

一、最关键的一个配置类
自定义一个SecurityConfig类继承自WebSecurityConfigurerAdapter抽象类,实现三个主要的方法:

	/**
     * 1.身份认证接口
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
    }
	/**
     * 2.web层静态资源放行
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers(
                "/**/*.css",
                "/**/*.js",
                "/img/**",
                "/admin/images/**"
        );
    }
	/**
     * 3.接口API拦截
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception{
        System.out.println("进入configure方法");

        //表单登录
        http.formLogin()
                //自定义登录页面
                .loginPage("/toLogin")
                .usernameParameter("username")
                .passwordParameter("password")
                //自定义登录逻辑
                .loginProcessingUrl("/doLogin")
                //登录成功后的跳转页面
                //.successForwardUrl("/toIndex")    //转发
                .successHandler(successHandler) //重定向
                //登录失败后的跳转页面
                //.failureForwardUrl("/toError");   //转发
                .failureHandler(failureHandler);//重定向

        //授权
        http.authorizeRequests()
                //放行登录页面
                .antMatchers("/toLogin").permitAll()
                //放行失败页面
                .antMatchers("/to404").permitAll()
                //放行权限不足页面
                .antMatchers("/to403").permitAll()
                //放行验证码
                .antMatchers("/getImage").permitAll()
                //放行获得主体信息接口
                .antMatchers("/getPrincipal").permitAll()
                //放行官网信息接口
                .antMatchers("/toIndex").permitAll()
                //放行官网信息接口
                .antMatchers("/toDevice").permitAll()
                //放行官网信息接口
                .antMatchers("/toHome").permitAll()
                //所有请求都必须被认证
                .anyRequest().authenticated();

        //注销
        http.logout()
                //退出登录url
                .logoutUrl("/logout")
                //退出登录成功跳转url
                .logoutSuccessUrl("/toLogin");

        //异常处理(例如权限不足)
        http.exceptionHandling()
                .accessDeniedHandler(new MyAccessDeniedHandler("/to403"));  //重定向

        //记住我
        http.rememberMe()
                //自定义登录逻辑
                .userDetailsService(userDetailsService)
                //指定存储位置
                .tokenRepository(tokenRepository);

         //将过滤器配置在UsernamePasswordAuthenticationFilter之前
        http.addFilterBefore(new VerificationCodeFilter(failureHandler), UsernamePasswordAuthenticationFilter.class);

        //单点登录
        //http.sessionManagement()
        //        .maximumSessions(1)
        //        .maxSessionsPreventsLogin(false);

        //关闭csrf防护
        http.csrf().disable();
    }

记得加上两个必须的注解:

@Configuration  //相当于Spring的xml配置文件,在这个类方法的返回值是java对象,这些对象存放在spring容器中
@EnableWebSecurity  //表示启用SpringSecurity安全框架的功能

二、将登录的SysUser类实现UserDetails接口

@Data
@Accessors(chain = true)
@AllArgsConstructor
@NoArgsConstructor
public class SysUser implements UserDetails {

    private Integer id;
    /**
     * 用户名
     */
    private String username;

    /**
     * 密码
     */
    private String password;

    /**
     * 真实姓名
     */
    private String realName;

    /**
     * 创建时间
     */
    private String createTime;

    /**
     * 最近登录时间
     */
    private String loginTime;

    /**
     * 是否可用
     */
    private Boolean isenable;

    /**
     * 用户所拥有的权限
     */
    private List<? extends GrantedAuthority> authorities;

    /**
     * 用户的账号是否过期,过期的账号无法通过授权验证. true 账号未过期
     */
    private Boolean accountNonExpired = true;

    /**
     * 用户的账户是否被锁定,被锁定的账户无法通过授权验证. true 账号未锁定
     */
    private Boolean islock = true;

    /**
     * 用户的凭据(pasword) 是否过期,过期的凭据不能通过验证. true 没有过期,false 已过期
     */
    private Boolean iscredentials = true;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return authorities;
    }

    @Override
    public String getPassword() {
        return password;
    }

    @Override
    public String getUsername() {
        return username;
    }

    @Override
    public boolean isAccountNonExpired() {
        return accountNonExpired;
    }

    @Override
    public boolean isAccountNonLocked() {
        return islock;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return iscredentials;
    }

    @Override
    public boolean isEnabled() {
        return isenable;
    }

}

3、同时自定义一个类实现UserDetailsService接口

@Service("myUserDetailService")
public class MyUserDetailService implements UserDetailsService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private PermissionMapper permissionMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        SysUser sysUser = userMapper.findUserByUserName(username);
        if(sysUser!=null){
            List<SysRole> roleList = roleMapper.findRoleByUserId(sysUser.getId());
            List<SysPermission> permissionList = permissionMapper.findMenuByUserId(sysUser.getId());
            List<GrantedAuthority> list=new ArrayList<>();
            //查询用户具有的角色
            for (SysRole sysRole:roleList) {
                GrantedAuthority grantedAuthority=new SimpleGrantedAuthority("ROLE_"+sysRole.getRoleName());
                list.add(grantedAuthority);
            }
            //查询用户具有的权限
            for (SysPermission permission:permissionList){
                GrantedAuthority grantedAuthority=new SimpleGrantedAuthority(permission.getPermissionUrl());
                list.add(grantedAuthority);
            }
            sysUser.setAuthorities(list);
            SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String nowDate = sdf.format(new Date());
            sysUser.setLoginTime(nowDate);
            //记录登录时间
            userMapper.updateLoginTime(sysUser);
            System.out.println("list="+list);
        }else {
            throw new UsernameNotFoundException("用户名不存在!");
        }
        return sysUser;
    }
}

你可能感兴趣的:(Spring,Security,java)