1. 程式人生 > >SpringBoot中使用spring security進行安全控制

SpringBoot中使用spring security進行安全控制

一、引入

在SpringBoot中引入SpringSecurity

<!--spring boot security引入-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
</dependency>

二、建立許可權基本相關類

目的是讓使用者擁有某種許可權角色,以訪問那些設定許可權的資源
1. 建立使用者類

@Entity
@Table(name="user")
public class User {
    @Id
    @GeneratedValue
    @JsonIgnore private long id; //jasonIgnore返回時用來在直接返回忽略一些欄位
    private String name;
    @JsonIgnore    private String password;
    @JsonIgnore    private List<Role> roles;
    //與角色表進行關聯,並建立一張新表來維護二者關係
    @ManyToMany
(cascade = {CascadeType.REFRESH},fetch = FetchType.EAGER) @JoinTable(name = "user_role", joinColumns = {@JoinColumn(name = "user_id")}, inverseJoinColumns = {@JoinColumn(name = "roles_id")}) //get/set省略 }

2.建立角色類

@Entity
@Table(name = "role")
public class Role {
    @Id
@GeneratedValue private long id; private String name; public Role(){} .... }

3.在系統使用者中組裝user,以便在系統auth.userDetailsService獲取符合該類的資訊


public class SecurityUser extends User implements UserDetails
{

    private static final long serialVersionUID = 1L;
    public SecurityUser(User user) {
        if(user != null)
        {
            this.setId(user.getId());
            this.setName(user.getName());
            this.setPassword(user.getPassword());
            this.setRoles(user.getRoles());
        }
    }
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        Collection<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
        List<Role> roles = this.getRoles();
        if(roles != null)
        {
            for (Role role : roles) {
                SimpleGrantedAuthority authority = new SimpleGrantedAuthority(role.getName());
                authorities.add(authority);
            }
        }
        return authorities;
    }

    @Override
  @JsonIgnore  public String getPassword() {
        return super.getPassword();
    }

    @Override
    public String getUsername() {
        return super.getName();
    }
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }
    @Override
    public boolean isEnabled() {
        return true;
    }

}

4.建立UserService

@Component
public class UserService implements UserDetailsService {
    @Autowired
    private SysUserRepository userRepository;
    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        User user = userRepository.findByName(s);
        if (user == null) {
            throw new UsernameNotFoundException("使用者名稱不存在");
        }
        System.out.println("s:"+s);
        System.out.println("username:"+user.getName()+";password:"+user.getPassword());
        return new SecurityUser(user);
    }
}

註釋:

  1. User 與Role類是多對多的關係,比如一個管理員使用者,可以有普通使用者的許可權,和管理員的許可權,因此我建立了一張user_role表來維護他們之間的關係
  2. SecurityUser和UserService組合,一個實現的是UserDetails類一個實現的是UserDetailsService類,在下邊的安全配置類中需要用這個UserDetailsService的物件,實現登入的驗證
  3. SecurityUser類實現了對系統對使用者的要求的組裝

三、建立許可權配置類

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean //即返回上邊建立的UserService類物件
        UserDetailsService customUserService() {
            return new UserService();
        }
        @Override
      protected void configure(AuthenticationManagerBuilder auth)
      throwsException{
        auth.userDetailsService(customUserService())//就返回的物件,進行密碼驗證
        .passwordEncoder(passwordEncoder());//我這裡採取的是 BCrypt加密演算法
        }
   @Bean
   public BCryptPasswordEncoder passwordEncoder() {
        return   new BCryptPasswordEncoder();
    }
    @Override
        protected void configure(HttpSecurity http) 
        throws Exception {
            http.authorizeRequests().
                    antMatchers("/",
                 .permitAll()
                    .antMatchers("/manage/**").hasRole("ADMIN")
                    .anyRequest().authenticated().
                    and().
                    formLogin().
                    loginProcessingUrl("/login").
                    usernameParameter("username")
                    .passwordParameter("password")
                    .defaultSuccessUrl("/login1")//成功後跳轉介面
                    .and()
                    .logout().logoutUrl("/logout")//登出預設api
                    .and()
                    //開啟cookie儲存使用者資料
                    .rememberMe()
                    //設定cookie有效期
                    .tokenValiditySeconds(60 * 60 * 24 * 7)
                    .and()
                    .logout().permitAll()
                    .and().csrf().disable();
        }


    }

註釋:

  1. 首先用到了auth.userDetailsService(customUserService()),就是用來獲取我們查詢到的相關資訊
  2. .passwordEncoder(passwordEncoder())進行密碼比較,方法為我們建立使用者物件時採用的加密方法,即將資料庫的儲存的加密密碼,和使用者登入提交的程式碼通過此方式進行加密後進行比對,如果前期想要明文儲存進行測試的話,可以自己建立加密類,如下:
public class MyPasswordEncoder implements PasswordEncoder {

    @Override
    public String encode(CharSequence arg0) {
        return arg0.toString();
    }

    @Override
    public boolean matches(CharSequence arg0, String arg1) {
        return arg1.equals(arg0.toString());
    }

}

註釋接上:

3.protected void configure(HttpSecurity http),則是我們進行許可權控制的主要部分, http.authorizeRequests().antMatchers(” “,” “).permitAll()中填入不用登入驗證開放api介面,當然介面分為兩類,一類是不需要登入驗證就能訪問的,所以我把他們放到了前面的位置,如果想設定某些網址需要驗證帳號登入並且有某種許可權時可以在網址後接.hasRole(“ADMIN”).anyRequest().authenticated()。

注意role的寫法,一般設定許可權角色時在資料庫儲存時常常寫成ROLE_ADMIN,在這裡只需要後半部分就可以了

4.and(). formLogin()此後部分是登入驗證的設定,我們設定以帳號密碼的登入方式,那麼usernameParameter(“username”) .passwordParameter(“password”),就是在登入驗證時採用的post請求時欄位key的值, loginProcessingUrl(“/login”)是進行登入處理的頁面,因為,我寫的專案是純為安卓設定的資料大部分都是用json的所以就預設用了”/login”,這是一個系統自帶的簡陋介面,如果需要自定義頁面進行的話,可以參考其他教程。
5.其餘的配置上邊有註釋,就不多說了


                           系統自帶登入介面

這裡寫圖片描述


                            登入跳轉介面:

這裡寫圖片描述