首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Spring Security 核心原理與數據庫認證授權實戰

     編輯:Java 綜合教學

Spring Security 核心原理與數據庫認證授權實戰

Spring Security 的核心職責是認證與授權:

  • 認證:驗證主體身份(用戶、設備、系統),確認「你是誰」。
  • 授權:判斷已認證主體是否有權限執行某操作,確認「你能做什麼」。

基礎配置:Servlet Filter 鏈

<!-- web.xml -->
<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

獲取當前認證用戶信息

Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String username;
if (principal instanceof UserDetails) {
    username = ((UserDetails) principal).getUsername();
} else {
    username = principal.toString();
}

核心接口:數據庫驅動的認證授權

Spring Security 提供兩大核心接口實現自定義用戶/權限加載:

  • UserDetails:封裝用戶核心信息(用戶名、密碼、權限集合、賬戶狀態等)。
  • UserDetailsService:單方法接口 loadUserByUsername(String username),負責從數據庫查詢並構建 UserDetails 對象。

實戰:基於 Hibernate/JPA 的用戶權限模型

1. 用戶實體

@Entity
@Table(name = "sys_user")
public class SysUser implements UserDetails {
    @Id @GeneratedValue
    private Long id;
    private String username;
    private String password;
    @ManyToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "sys_user_role", joinColumns = @JoinColumn(name = "user_id"),
        inverseJoinColumns = @JoinColumn(name = "role_id"))
    private Set roles;
    // 實現 UserDetails 方法:getAuthorities() 返回角色/權限集合
    // isAccountNonExpired、isAccountNonLocked、isCredentialsNonExpired、isEnabled 均返回 true
}

2. 角色/權限實體

@Entity
@Table(name = "sys_role")
public class SysRole implements GrantedAuthority {
    @Id @GeneratedValue
    private Long id;
    private String name; // e.g. ROLE_ADMIN
    private String description;
    @Override public String getAuthority() { return name; }
}

3. 實現 UserDetailsService

@Service
public class CustomUserDetailsService implements UserDetailsService {
    @Autowired private UserRepository userRepository;

    @Override
    @Transactional(readOnly = true)
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        SysUser user = userRepository.findByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException("用戶不存在: " + username);
        }
        return user; // SysUser 已實現 UserDetails
    }
}

4. Security 配置類

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired private CustomUserDetailsService userDetailsService;
    @Autowired private PasswordEncoder passwordEncoder;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/login", "/css/**", "/js/**").permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin().loginPage("/login").permitAll()
            .and()
            .logout().permitAll()
            .and()
            .csrf().disable(); // 簡化演示,生產請啟用 CSRF 保護
    }
}

進階:方法級權限控制

@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
    // 配置方法級表達式處理器等
}

在 Service 方法上使用註解:

@PreAuthorize("hasRole('ADMIN')")
public void deleteUser(Long id) { ... }

@PostAuthorize("returnObject.owner == authentication.name")
public Document findById(Long id) { ... }

總結

通過實現 UserDetailsService 並配合 UserDetails 實體,Spring Security 能無縫對接任意關係型數據庫,實現靈活的認證授權體系。結合方法級安全註解,可實現細粒度的業務權限控制。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved