zoukankan      html  css  js  c++  java
  • Spring Security构建Rest服务-0700-SpringSecurity开发基于表单的认证

    自定义用户认证逻辑:

      1,处理用户信息获取,2,用户校验,3密码的加密解密

    新建:MyUserDetailService类,实现UserDetailsService接口。

    UserDetailsService接口代码:只有一个方法,通过用户名获取用户信息,返回UserDetail

    public interface UserDetailsService {
      
        UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
    }

    UserDetail:记录了  账户是否启用、账户是否过期、密码是否过期、账户是否锁定、权限集合信息

    public interface UserDetails extends Serializable {
        // ~ Methods
        // ========================================================================================================
    
        /**
         * Returns the authorities granted to the user. Cannot return <code>null</code>.
         *
         * @return the authorities, sorted by natural key (never <code>null</code>)
         */
        Collection<? extends GrantedAuthority> getAuthorities();
    
        /**
         * Returns the password used to authenticate the user.
         *
         * @return the password
         */
        String getPassword();
    
        /**
         * Returns the username used to authenticate the user. Cannot return <code>null</code>
         * .
         *
         * @return the username (never <code>null</code>)
         */
        String getUsername();
    
        /**
         * Indicates whether the user's account has expired. An expired account cannot be
         * authenticated.
         *
         * @return <code>true</code> if the user's account is valid (ie non-expired),
         * <code>false</code> if no longer valid (ie expired)
         */
        boolean isAccountNonExpired();
    
        /**
         * Indicates whether the user is locked or unlocked. A locked user cannot be
         * authenticated.
         *
         * @return <code>true</code> if the user is not locked, <code>false</code> otherwise
         */
        boolean isAccountNonLocked();
    
        /**
         * Indicates whether the user's credentials (password) has expired. Expired
         * credentials prevent authentication.
         *
         * @return <code>true</code> if the user's credentials are valid (ie non-expired),
         * <code>false</code> if no longer valid (ie expired)
         */
        boolean isCredentialsNonExpired();
    
        /**
         * Indicates whether the user is enabled or disabled. A disabled user cannot be
         * authenticated.
         *
         * @return <code>true</code> if the user is enabled, <code>false</code> otherwise
         */
        boolean isEnabled();
    }

    MyUserDetailService:

    package com.imooc.security.browser;
    
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.security.core.authority.AuthorityUtils;
    import org.springframework.security.core.userdetails.User;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.core.userdetails.UsernameNotFoundException;
    import org.springframework.security.crypto.password.PasswordEncoder;
    import org.springframework.stereotype.Component;
    
    /**
     * UserDetailsService是SpringSecurity的一个接口,
     * 只有一个方法:根据用户名获取用户详情
     * ClassName: MyUserDetailService 
     * @Description: TODO
     * @author lihaoyang
     * @date 2018年2月28日
     */
    @Component
    public class MyUserDetailService implements UserDetailsService{
        
        private Logger logger = LoggerFactory.getLogger(getClass());
        
        @Autowired
        private PasswordEncoder passwordEncoder;
        
        /**
         * UserDetails接口,实际可以自己实现这个接口,返回自己的实现类
         */
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            logger.info("登录用户名:"+username);
            //根据用户名查询用户信息
            
            //User:springsecurity 对 UserDetails的一个实现
            //为了演示在这里用passwordEncoder加密一下密码,实际中在注册时就加密,此处直接拿出密码
            String password = passwordEncoder.encode("123456");
            System.err.println("加密后密码:  "+password);
            //参数:用户名|密码|是否启用|账户是否过期|密码是否过期|账户是否锁定|权限集合
            return new User(username,password,true,true,true,true,AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
        }
    
    }

    在BrowserSecurityConfig里配置PasswordEncoder,用来加密密码的一个接口:

    @Configuration //这是一个配置
    public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter{
    
        //注意是org.springframework.security.crypto.password.PasswordEncoder
        @Bean
        public PasswordEncoder passwordencoder(){
            //BCryptPasswordEncoder implements PasswordEncoder
            return new BCryptPasswordEncoder();
        }
        
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            //实现需要认证的接口跳转表单登录,安全=认证+授权
            //http.httpBasic() //这个就是默认的弹框认证
            http.formLogin() //表单认证 
                .and()
                .authorizeRequests() //下边的都是授权的配置
                .anyRequest()        //任何请求
                .authenticated();    //都需要身份认证
        }
    }

    PasswordEncoder代码:一个加密方法,一个匹配方法,注意是org.springframework.security.crypto.password包里的接口,这个接口的实现类会给加密的密码随机加盐,所以一样的密码每次加密出来是不一样的,更安全。如123456加密2次:

    加密后密码:  $2a$10$BChH.C4.X8MYuI1mHFoOkefWhOsad7SvhZedHFt1OG4vjSu.z9weC

    加密后密码:  $2a$10$YUbz.miE5C0aAcuU1FnHSu/U.Qm/BujTNw6X7S5i4/6AhjyDc6suK

    package org.springframework.security.crypto.password;
    
    /**
     * Service interface for encoding passwords.
     *
     * The preferred implementation is {@code BCryptPasswordEncoder}.
     *
     * @author Keith Donald
     */
    public interface PasswordEncoder {
    
        /**
         * Encode the raw password. Generally, a good encoding algorithm applies a SHA-1 or
         * greater hash combined with an 8-byte or greater randomly generated salt.
         */
        String encode(CharSequence rawPassword);
    
        /**
         * Verify the encoded password obtained from storage matches the submitted raw
         * password after it too is encoded. Returns true if the passwords match, false if
         * they do not. The stored password itself is never decoded.
         *
         * @param rawPassword the raw password to encode and match
         * @param encodedPassword the encoded password from storage to compare with
         * @return true if the raw password, after encoding, matches the encoded password from
         * storage
         */
        boolean matches(CharSequence rawPassword, String encodedPassword);
    
    }

    访问:http://localhost:8080/user

     输入正确的密码123456:可以访问user查询服务

    完整代码GitHub:https://github.com/lhy1234/spring-security

  • 相关阅读:
    Python爬取中国疫情的实时数据
    文件上传
    条件查询和分页(第三周)
    全国疫情可视化图表
    Jquery的Ajax技术(第二周)
    软件工程开课博客
    求一个整数数组、环形数组中最大子数组的和
    今日所学—Android中ViewPager的使用
    今日所学—Android中ExpandableListView的使用
    你看,蚂蚁金服都上市了,程序员什么时候才能财富自由呢?
  • 原文地址:https://www.cnblogs.com/lihaoyang/p/8483324.html
Copyright © 2011-2022 走看看