1. 程式人生 > >SpringSecurity(二)基於資料庫使用者登入

SpringSecurity(二)基於資料庫使用者登入

一、使用SpringSecurity提用的User物件


1. 新建一個MyUserService類

@Component
public class MyUserService implements UserDetailsService {
    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        //  省略從資料庫中獲取使用者資訊的過程...
        //  通過使用者名稱s去資料庫裡查詢使用者以及使用者許可權
        //  然後返回User物件,注意,這裡的User物件是org.springframework.security.core.userdetails.User
        return new User(s,new BCryptPasswordEncoder().encode("123456"),AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_ADMIN,ROLE_USER"));
    }
}

這個類實現了UserDetailsService介面,裡面有一個loadUserByUsername(String s)方法,這個方法返回一個UserDetails ,UserDetails 是一個介面,而org.springframework.security.core.userdetails.User實現了UserDetails,因此這裡我們可以直接使用SpringSecurity提供的User物件,當然如果不想使用SpringSecurity提供的User物件,我們也可以自己編寫一個實現UserDetails介面的物件。

2. SpringSecurityConfig類程式碼如下

@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private MyUserService myUserService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/authentication/*","/login") // 不需要登入就可以訪問
                .permitAll()
                .antMatchers("/user/**").hasAnyRole("USER") // 需要具有ROLE_USER角色才能訪問
                .antMatchers("/admin/**").hasAnyRole("ADMIN") // 需要具有ROLE_ADMIN角色才能訪問
                .anyRequest().authenticated()
                .and()
                    .formLogin()
                    .loginPage("/authentication/login") // 設定登入頁面
                    .loginProcessingUrl("/authentication/form")
                    .defaultSuccessUrl("/user/index") // 設定預設登入成功後跳轉的頁面
                ;
    }

    // 密碼加密方式
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
    // 重寫方法,自定義使用者
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//        auth.inMemoryAuthentication().withUser("lzc").password(new BCryptPasswordEncoder().encode("123456")).roles("ADMIN","USER");
//        auth.inMemoryAuthentication().withUser("zhangsan").password(new BCryptPasswordEncoder().encode("123456")).roles("USER");
        auth.userDetailsService(myUserService); // 注入MyUserService,這樣SpringSecurity會呼叫裡面的loadUserByUsername(String s)
    }
}

 

二、使用自定義的使用者物件

1. 新建一個LoginUser物件,拓展更多的使用者屬性

public class LoginUser implements UserDetails, CredentialsContainer {

    private String password;
    private  String username;
    private  Set<GrantedAuthority> authorities;
    private  boolean accountNonExpired;
    private  boolean accountNonLocked;
    private  boolean credentialsNonExpired;
    private  boolean enabled;

    private String nickName;

    public LoginUser() {
        this("", "", true, true, true, true, null);
    }

    public LoginUser(String username, String password, Collection<? extends GrantedAuthority> authorities) {
        this(username, password, true, true, true, true, authorities);
    }

    public LoginUser(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
        if (username != null && !"".equals(username) && password != null) {
            this.username = username;
            this.password = password;
            this.enabled = enabled;
            this.accountNonExpired = accountNonExpired;
            this.credentialsNonExpired = credentialsNonExpired;
            this.accountNonLocked = accountNonLocked;

            this.authorities = new HashSet<>();
            for (GrantedAuthority g : authorities) {
                this.authorities.add(g);
            }

        } else {
            throw new IllegalArgumentException("Cannot pass null or empty values to constructor");
        }
    }


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

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

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

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

    @Override
    public Set<GrantedAuthority> getAuthorities() {
        return authorities;
    }

    public void setAuthorities(Set<GrantedAuthority> authorities) {
        this.authorities = authorities;
    }

    public String getNickName() {
        return nickName;
    }

    public void setNickName(String nickName) {
        this.nickName = nickName;
    }

    @Override
    public void eraseCredentials() {
        this.password = null;
    }

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

    @Override
    public boolean isAccountNonLocked() {
        return this.accountNonLocked;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return this.credentialsNonExpired;
    }

    @Override
    public boolean isEnabled() {
        return this.enabled;
    }
}

2. 修改MyUserService類

@Component
public class MyUserService implements UserDetailsService {
    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        //  省略從資料庫中獲取使用者資訊的過程...
        //  通過使用者名稱s去資料庫裡查詢使用者以及使用者許可權
        //  然後返回User物件,注意,這裡的User物件是org.springframework.security.core.userdetails.User
        // return new User(s,new BCryptPasswordEncoder().encode("123456"),AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_ADMIN,ROLE_USER"));

        List<GrantedAuthority> authorityLists = AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_ADMIN,ROLE_USER");
        LoginUser loginUser = new LoginUser(s,new BCryptPasswordEncoder().encode("123456"),authorityLists);
        loginUser.setNickName("成");
        return loginUser;
    }
}

程式碼地址  https://github.com/923226145/SpringSecurity/tree/master/chapter2