1. 程式人生 > >spring security 基本配置

spring security 基本配置

給大家推薦個靠譜的公眾號程式設計師探索之路,大家一起加油

git專案地址:https://github.com/ZhZGod/spring-security-demo.git

1.實現

org.springframework.security.core.userdetails.UserDetailsService,這裡可以定義從哪裡得到使用者資訊,以及分裝成security的user

import com.zzh.entity.UserEntity;
import com.zzh.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class MyUserDetailsService implements UserDetailsService {

    @Autowired
    private UserService userService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        UserEntity userEntity = userService.getByUsername(username);
        if (userEntity == null){
            throw new UsernameNotFoundException("使用者不存在!");
        }
        List<SimpleGrantedAuthority> simpleGrantedAuthorities = createAuthorities(userEntity.getRoles());
        return new User(userEntity.getUsername(), userEntity.getPassword(), simpleGrantedAuthorities);
    }

    /**
     * 根據自己的實際情況可以進行 自定義 我的是user表裡有一個欄位儲存的許可權而且是,號分隔的
     * 許可權字串轉化
     * @param roleStr 許可權字串
     */
    private List<SimpleGrantedAuthority> createAuthorities(String roleStr){
        String[] roles = roleStr.split(",");
        List<SimpleGrantedAuthority> simpleGrantedAuthorities = new ArrayList<>();
        for (String role : roles) {
            simpleGrantedAuthorities.add(new SimpleGrantedAuthority(role));
        }
        return simpleGrantedAuthorities;
    }

}

2.WebSecurityConfig,具體作用見程式碼註釋

import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

import javax.annotation.PostConstruct;

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)//使用註解的許可權形式時 這個註解和下面的authenticationManagerBean要加上
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
    @Autowired
    private MyUserDetailsService myUserDetailsService;
    @Autowired
    private AuthenticationManagerBuilder authenticationManagerBuilder;
    @Autowired
    private MyConfig myConfig;

    /**
     * 指定  校驗使用者資訊的地方  和 密碼編碼方式
     */
    @PostConstruct
    public void init() {
        try {
            authenticationManagerBuilder
                    .userDetailsService(myUserDetailsService)
                    .passwordEncoder(myConfig.passwordEncoder());
        } catch (Exception e) {
            throw new BeanInitializationException("Security configuration failed", e);
        }
    }

    /**
     * 忽略的路徑
     * @param web
     * @throws Exception
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring()
                .antMatchers(HttpMethod.OPTIONS, "/**")
                .antMatchers("/app/**/*.{js,html}")
                .antMatchers("/bower_components/**")
                .antMatchers("/i18n/**")
                .antMatchers("/content/**")
                .antMatchers("/swagger-ui/index.html")
                .antMatchers("/test/**")
                .antMatchers("/h2-console/**")
                .antMatchers("/mylogin");
    }
    /**
     * 匹配 "/", "/index", "/mylogin", "/register" 路徑,不需要許可權即可訪問
     * 登入地址為 "/mylogin",登入成功預設跳轉到頁面 "/user"
     * 退出登入的地址為 "/logout",退出成功後跳轉到頁面 "/login"
     * 預設啟用 CSRF 我這裡給禁用了
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .authorizeRequests()
                .antMatchers("/", "/index", "/mylogin", "/register").permitAll()//在這地方也可以配置哪些路徑不需要許可權
                //.antMatchers("/user/**").hasRole("USER")//不使用註解也可以在這裡配置 /user/以下的 路徑 都需要USER許可權
                //.antMatchers("/user").hasRole("USER")//   /user路徑需要USER許可權
                .anyRequest().authenticated()//其餘的所有請求都需要驗證
                .and()
                .formLogin().loginPage("/mylogin").defaultSuccessUrl("/user")//自定義 登入頁面的地址  登入成功後的地址
                .and()
                .logout().logoutUrl("/logout").logoutSuccessUrl("/login");//自定義 登出的地址  登出成功後的地址
    }

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}

3.security 自帶的有登入/login和登出/logout介面,當然 可以自定義

附錄:

MyConfig

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
public class MyConfig {
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    //    @Bean  示例 自己寫加密方式
//    public PasswordEncoder passwordEncoder() {
//        return new MyPasswordEncoder();
//    }
}

MyPasswordEncoder:

import org.springframework.security.crypto.password.PasswordEncoder;

public class MyPasswordEncoder implements PasswordEncoder {
    /**
     * 只是在原有的密碼基礎上增加了"1"字元
     * @param rawPassword
     * @return
     */
    public String encode(CharSequence rawPassword) {
        return rawPassword.toString()+"1";
    }

    public boolean matches(CharSequence rawPassword, String encodedPassword) {
        if (encodedPassword != null && encodedPassword.length() != 0) {
            if ((rawPassword.toString()+"1").equals(encodedPassword)){
                return true;
            }
        }
        return false;
    }
}