美文网首页Spring Security
Spring Boot + Security实现简单验证登录操作

Spring Boot + Security实现简单验证登录操作

作者: double_Ji | 来源:发表于2018-09-09 22:13 被阅读238次

    利用spring security 实现简单的登陆验证,并且在登陆失败或者成功后进行对前端返回的处理。

    GitHub地址

    1.准备(数据库配置等)

    本例子使用的Mysql + Hibernate

    image

    2.引入maven依赖

    本例子需要的依赖有

    基本的mysql,jpa,还有spring security的oauth2,jwt

    image

    3.新建表User,UserRole

    创建entity:User和UserRole,在本例子中实际上只有User一个表就够了,毕竟只是验证用户名和密码嘛,但是我习惯每次创建User就手痒价格Role的表。

    2个表多对多的关系也在代码中有用Hibernate写了,感兴趣的可以在Git上看一下。

    
    /**
    
    * Store User information.
    
    */
    
    @Entity
    
    @Table(name ="sys_user")
    
    public class User {
    
    private StringuserName;
    
        private StringuserDescription;
    
        private Stringpassword;
    
        private Listroles;
    
        @Id
    
        @Column(name ="user_name")
    
    public StringgetUserName() {
    
    return userName;
    
        }
    
    public void setUserName(String userName) {
    
    this.userName = userName;
    
        }
    
    @Column(name ="user_desc")
    
    public StringgetUserDescription() {
    
    return userDescription;
    
        }
    
    public void setUserDescription(String userDescription) {
    
    this.userDescription = userDescription;
    
        }
    
    @Column(name ="password")
    
    public StringgetPassword() {
    
    return password;
    
        }
    
    public void setPassword(String password) {
    
    this.password = password;
    
        }
    
    @ManyToMany
    
        @JoinTable(name ="sys_user_role",
    
                joinColumns =@JoinColumn(name ="user_name", referencedColumnName ="user_name", updatable =false, insertable =false),
    
                inverseJoinColumns =@JoinColumn(name ="role_code", referencedColumnName ="role_code", updatable =false, insertable =false))
    
    public ListgetRoles() {
    
    return roles;
    
        }
    
    public void setRoles(List roles) {
    
    this.roles = roles;
    
        }
    
    }
    
    

    4.User Repository

    此处只需要添加两个方法,findByUserName在UserDetialService load user的信息时候用,一个是测试用。

    
    @Repository
    
    public interface UserRepositoryextends JpaRepository {
    
    UserfindByUserName(String userName);
    
        @Query(value ="select r.roleCode from User u inner join u.roles as r where u.userName = :userName")
    
    ListqueryUserOwnedRoleCodes(@Param(value ="userName") String userName);
    
    }
    
    

    5.新建DatabaseUserDetailsService

    新建DatabaseUserDetailsService继承UserDetailsService,并重写loadUserByUsername方法,在用户登陆时,spring会调用这个方法去获得user的信息(密码等),以对比页面传过来的用户名和密码是否正确。

    
    @Override
    
    public UserDetailsloadUserByUsername(String userName)throws UsernameNotFoundException {
    
    User user =userRepository.findByUserName(userName);
    
        if (user ==null) {
    
    //throw exception inform front end not this user
    
            throw new UsernameNotFoundException("user + " + userName +"not found.");
    
        }
    
    List roleCodeList =userRepository.queryUserOwnedRoleCodes(userName);
    
        List authorities =
    
    roleCodeList.stream().map(e ->new SimpleGrantedAuthority(e)).collect(Collectors.toList());
    
        UserDetails userDetails =new org.springframework.security.core.userdetails.User(
    
    user.getUserName(),user.getPassword(),authorities);
    
        return userDetails;
    
    }
    
    

    6.新建WebSecuerityConfig

    建立一个WebSecuerityConfig类继承WebSecurityConfigurerAdapter,并重写两个configure方法,

    配置各种访问权限限制以及添加处理类

    (1)不需要限制的用permitAll()放行即可。

    (2).successHandler() 和 .failureHandler() 是配置登录失败或成功时的处理,后面有写这两个类的实现。

    (3).authenticationEntryPoint()是没有登录就请求资源时的处理。

    
    @Override
    
    public void configure(HttpSecurity http)throws Exception {
    
    http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
    
    .and().csrf().disable()
    
    .authorizeRequests()
    
    .antMatchers("/v2/api-docs/**").permitAll()
    
    .anyRequest().authenticated()
    
    .and().formLogin().loginProcessingUrl("/api/login")
    
    .successHandler(successHandler)
    
    .failureHandler(failHandler)
    
    .and().exceptionHandling().authenticationEntryPoint(entryPoint);
    
    }
    
    @Override
    
    protected void configure(AuthenticationManagerBuilder auth)throws Exception {
    
    auth.userDetailsService(userDetailsService);
    
    }
    
    

    7.登陆失败或成功的处理。

    未登录就请求资源时,spring会交给AuthenticationEntryPoint处理。

    登陆成功之后,spring会跳到AuthenticationFailHandler。

    登陆失败之后,spring会跳到AuthenticationSuccessHandler。

    所以我们要继承这两个方法,把想要返回给页面的信息在这两个类中写一下。

    
    @Service("authenticationEntryPointImpl")
    
    public class AuthenticationEntryPointImplimplements AuthenticationEntryPoint {
    
    @Override
    
        public void commence(HttpServletRequest httpServletRequest,
    
                            HttpServletResponse httpServletResponse, AuthenticationException e)throws IOException {
    
    httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, e.getMessage());
    
        }
    
    }
    
    
    
    @Service("authenticationSuccessHandler")
    
    public class AuthenticationSuccessHandlerextends SavedRequestAwareAuthenticationSuccessHandler {
    
    @Override
    
        public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response
    
    , Authentication authentication)throws IOException {
    
    logger.info("User: " + request.getParameter("username") +" Login successfully.");
    
            this.returnJson(response);
    
        }
    
    private void returnJson(HttpServletResponse response)throws IOException {
    
    response.setStatus(HttpServletResponse.SC_OK);
    
            response.setCharacterEncoding("UTF-8");
    
            response.setContentType("application/json");
    
            response.getWriter().println("{\"exceptionId\":\"null\",\"messageCode\":\"200\"," +
    
    "\"message\": \"Login successfully.\",\"serverTime\": " + System.currentTimeMillis() +"}");
    
        }
    
    }
    
    
    
    @Service("authenticationFailHandler")
    
    public class AuthenticationFailHandlerextends SimpleUrlAuthenticationFailureHandler {
    
    @Override
    
        public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception)throws IOException, ServletException {
    
    this.returnJson(response,exception);
    
        }
    
    private void returnJson(HttpServletResponse response,
    
                                AuthenticationException exception)throws IOException {
    
    response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
    
            response.setCharacterEncoding("UTF-8");
    
            response.setContentType("application/json");
    
            response.getWriter().println("{\"exceptionId\":\"null\",\"messageCode\":\"401\"," +
    
    "\"message\": \""+ exception.getMessage() +"\",\"serverTime\": " + System.currentTimeMillis() +"}");
    
        }
    
    }
    
    

    8.Postman 测试

    这是我数据库中存在的数据

    image

    没有登录直接发送普通时:

    image

    密码或用户名输入错误时,

    image

    用户名密码都正确时:

    image

    相关文章

      网友评论

        本文标题:Spring Boot + Security实现简单验证登录操作

        本文链接:https://www.haomeiwen.com/subject/tbzdgftx.html