Spring Boot [集成-Spring Security]

栏目: 后端 · 发布时间: 6年前

内容简介:Spring Boot [集成-Spring Security]

导读

在上一篇文章中对Spring Boot 集成Shrio做了一个简单的介绍,这篇文章中主要围绕Spring Boot 集成 Spring Security展开,文章末尾附有学习资料。

快速上手:

1.引入pom依赖

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

2.实现一个简单的用户权限类

用户权限功能的设计不是本篇文章的重点,这里以一个简单的例子作为演示,需要创建两个实体类一个枚举类

用户类:

@JsonIgnoreProperties(value = { "hibernateLazyInitializer","password" ,"new"})
@DynamicUpdate
@Entity
public class User extends AbstractPersistable<Long> {

    private static final long serialVersionUID = 2080627010755280022L;

    private String userName;

    @Column(unique = true, updatable = false)
    private String loginName;


    private String password;
    

    @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
    private Set<Role> roles;

    /**省略get/set**/
}

角色类别:

public enum RoleType {

    //級別从高到低 ADMIN->USER
    ADMIN,//管理员 

    USER//普通用户
}

角色类:

@Entity
public class Role extends AbstractPersistable<Long> {

    private static final long serialVersionUID = -856234002396786101L;

    @Enumerated(EnumType.STRING)
    @Column(name = "role_name", unique = true)
    private RoleType roleType;
}

3.定制自己的配置

首先需要从数据库中查询出来用户数据交给Spring Security这里有两种主要的方式:

AuthenticationProvider&&UserDetailsService两种方式的介绍:

Spring Security认证是由 AuthenticationManager 来管理的,但是真正进行认证的是 AuthenticationManager 中定义的 AuthenticationProvider。AuthenticationManager 中可以定义有多个 AuthenticationProvider。当我们使用 authentication-provider 元素来定义一个 AuthenticationProvider 时,如果没有指定对应关联的 AuthenticationProvider 对象,Spring Security 默认会使用 DaoAuthenticationProvider。DaoAuthenticationProvider 在进行认证的时候需要一个 UserDetailsService 来获取用户的信息 UserDetails,其中包括用户名、密码和所拥有的权限等。 所以如果我们需要改变认证的方式,我们可以实现自己的 AuthenticationProvider;如果需要改变认证的用户信息来源,我们可以实现 UserDetailsService。

a.实现UserDetailsService 接口

public class CustomUserDetailsService implements UserDetailsService {

    @Autowired UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByLoginName(username);
        if(user == null){
            throw new UsernameNotFoundException("not found");
        }
        List<SimpleGrantedAuthority> authorities = new ArrayList<>();
        authorities.add(new SimpleGrantedAuthority(user.getRole().name()));
        System.err.println("username is " + username + ", " + user.getRole().name());
        return new org.springframework.security.core.userdetails.User(user.getUsername(),
                user.getPassword(), authorities);
    }

}

将自己的配置托管给Sprng 管理,Security为我们提供了WebSecurityConfigurerAdapter 我们只需要根据自己的需要进行继承重写即可

@Configuration
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    @Bean
    public UserDetailsService userDetailsService() {
        return new CustomUserDetailsService();
    }

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

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/", "/index").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .defaultSuccessUrl("/admin")
                .permitAll()
                .and()
            .logout()
                .permitAll();
    }

}

b.实现 AuthenticationProvider接口

@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {

    private static final Logger logger = LoggerFactory.getLogger(CustomAuthenticationProvider.class);
   

    @Autowired
    private UserRepository userRepository;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String loginName = authentication.getName();
        String password = authentication.getCredentials().toString();
        List<GrantedAuthority> grantedAuths = new ArrayList<>();
        if (vaildateUser(loginName, password, grantedAuths)) {
            Authentication auth = new UsernamePasswordAuthenticationToken(loginName, password, grantedAuths);
            return auth;
        } else {
            return null;
        }
    }

    public boolean vaildateUser(String loginName, String password, List<GrantedAuthority> grantedAuths) {
        User user = userRepository.findByLoginName(loginName);
        if (user == null || loginName == null || password == null) {
            return false;
        }
        if (user.getPassword().equals(SHA.getResult(password)) && user.getUserStatus().equals(UserStatus.NORMAL)) {
            Set<Role> roles = user.getRoles();
            if (roles.isEmpty()) {
                grantedAuths.add(new SimpleGrantedAuthority(RoleType.USER.name()));
            }
            for (Role role : roles) {
                grantedAuths.add(new SimpleGrantedAuthority(role.getRoleType().name()));
                logger.debug("username is " + loginName + ", " + role.getRoleType().name());
            }
            return true;
        }
        return false;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return authentication.equals(UsernamePasswordAuthenticationToken.class);
    }
}

将配置托管给Spring

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private CustomAuthenticationProvider customAuthenticationProvider;
    

    @Override  
    protected void configure(AuthenticationManagerBuilder auth)  
            throws Exception {   
        auth.authenticationProvider(customAuthenticationProvider);
    }  

    @Override
    protected void configure(HttpSecurity http) throws Exception {
         http
            .authorizeRequests()
                .antMatchers("/", "/index").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .defaultSuccessUrl("/admin")
                .permitAll()
                .and()
            .logout()
                .permitAll();
    }

}

4.添加角色验证

我们将用户分成了管理员与普通用户,用户页面对用户与管理可见,管理员页面只对管理员可见

@Controller
public class UserController {

    PreAuthorize("hasAnyAuthority('ADMIN','USER')")
    @GetMapping("/user")
    public String user(){
        return "user";
    }
    
    @PreAuthorize("hasAnyAuthority('ADMIN')")@
    @GetMapping("/admin")
    public String admin(){
        return "admin";
    }
}

Spring Security虽然要比Apache Shiro功能强大,但作为Spring 自家的应用与Spring 整合确实非常简单,同样Spring Security 学习成本要比Apache Shiro高。

结语

这篇文章是匆忙中挤时间赶工出来的产物,有些地方也许写的有些问题,欢迎提出反馈。下篇文章打算用之前所学的技术做一个简单的项目,正在想做什么,欢迎提出建议。

学习资料:


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

云攻略

云攻略

马克·贝尼奥夫、卡莱尔·阿德勒 / 徐杰 / 海天出版社 / 2010年8月 / 36.00元

Apple、Google、甲骨文、腾讯 都已投入了云的怀抱, 你还在等什么? 快来加入我们! 最初,Salesforce.com 只是一间小小的租赁公寓 在短短10年内 它已成长为 世界上发展最快、最具创新力的 产业变革领导者 曾经,这是个软件为王的时代。 现在,这是个云计算的新时代。 NO SOFTWARE 抛弃软件的......一起来看看 《云攻略》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具