内容简介: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高。
结语
这篇文章是匆忙中挤时间赶工出来的产物,有些地方也许写的有些问题,欢迎提出反馈。下篇文章打算用之前所学的技术做一个简单的项目,正在想做什么,欢迎提出建议。
学习资料:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 持续集成:数据库集成及快速构建
- ShareSDK集成及集成后遇到的一些问题【原创】
- 持续集成与持续部署宝典Part 3:创建集成环境
- 持续集成与持续部署宝典Part 2:创建持续集成流水线
- 禅道 12.3.stable 版本发布,全面集成八种单元测试框架,打通持续集成闭环
- 持续集成将死
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。