前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring Security:自定义登录认证

Spring Security:自定义登录认证

作者头像
每天学Java
发布2020-06-02 09:50:28
1.4K0
发布2020-06-02 09:50:28
举报
文章被收录于专栏:每天学Java每天学Java

在昨天的文章中,我们使用Spring Boot实现了一个Security的应用,但是其中登录的方式和密码都是框架中自带的,今天我们来看一下如何自定义登录认证

首先说几个Spring Security的最核心组件(自认为):WebSecurityConfigurerAdapter;UserDetails;UserDetailsService;第一个类是自带的权限控制类,通过重写它的方法来设置一些web安全的细节,UserDetails是自带的实体类,UserDetailsService是自带的用户认证的类(主要通过它来实现自定义用户登录认证)。

01

首先我们来定义User实体类:

代码语言:javascript
复制
@Component
public class UserVO implements UserDetails,Serializable {

    private String username;
    private String password;
    private Collection<? extends GrantedAuthority> authorities;

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public void setAuthorities(Collection<? extends GrantedAuthority> authorities) {
        this.authorities = authorities;
    }

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

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

    @Override
    public String getUsername() {
        return this.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;
    }
}

然后是Service,这里的用户密码和用角色默认写死,大家可以根据实际情况去数据库中去取。

代码语言:javascript
复制
@Component
public class MyUserService implements UserDetailsService {
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        UserVO myUserDetails = new UserVO();
        //这里username就是我们表单中用户名,security在加载的时候会将值传到这里
        myUserDetails.setUsername(username);
        //模拟从数据库取出的密码
        myUserDetails.setPassword(new BCryptPasswordEncoder().encode("12345"));

        //模拟从数据库取出的权限
        HashSet<SimpleGrantedAuthority> set = new HashSet<>();
        //  set.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
        //角色名称
        set.add(new SimpleGrantedAuthority("ROLE_USER"));

        myUserDetails.setAuthorities(set);
        return myUserDetails;
    }
}

最后是权限控制了:这里重写了configuer方法(共有三个,这里重写了其中两个),注意参数的不同。AjaxResponseBody是一个封装的对象,定义了状态和信息

代码语言:javascript
复制
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private MyUserService myUserService; 
   @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests().anyRequest().permitAll()
                .and()
                .formLogin().loginPage("/login")
                //这个URL比较特殊, Security自带无需定义
                .successHandler(new AuthenticationSuccessHandler() {
                    @Override
                    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
                        System.out.println("登录成功");
                        AjaxResponseBody responseBody = new AjaxResponseBody();
                        responseBody.setStatus("200");
                        responseBody.setMsg("Login Success!");
      httpServletResponse.getWriter().write(JSON.toJSONString(responseBody));


                    }
                })
                .failureHandler(new AuthenticationFailureHandler() {
                    @Override
                    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
                        System.out.println("登录失败");
                        AjaxResponseBody responseBody = new AjaxResponseBody();
                        responseBody.setStatus("400");
                        responseBody.setMsg("Login Failure!");
                        httpServletResponse.getWriter().write(JSON.toJSONString(responseBody));
                    }
                })
                .permitAll()
                .and()
                .csrf().disable();//允许跨域
    }

    //自定义认证方式
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(myUserService).passwordEncoder(new BCryptPasswordEncoder());
    }
}

到这里我们就大功告成了,启动完用postman测试一下:

1.使用正确密码

2.使用错误密码

自定义登录认证到这里就实现了,也解决了昨天的第一个问题。那么第二个问题使用RESTful架构设计,如何实现权限认证呢?

其实通过上面我们就可以看到,自定义权限认证之后,登录成功和失败都会返回数据给客户端,当我们使用Restful架构时,我们可以在成功登录之后返回Token给客户端,这个Token保存用户信息,在后面请求的时候我们先判断Token是否合法,不合法走登录逻辑,合法我们去判断他的权限(有些请求等级低的用户无法请求),具体的实现我们留到下一篇文章。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-11-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 每天学Java 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档