maven配置

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

基于内存的简单应用

首先我们有两个不同的权限USER和ADMIN,分别能访问不同的页面

@Controller
@RequestMapping("/product")
public class ProductTestController {
	@RequestMapping("/info")
	@ResponseBody
	public String productInfo(){
		return " some product info ";
	}
}
-------------------------------------------
@Controller
@RequestMapping("/admin")
public class AdminTestController {
	@RequestMapping("/home")
	@ResponseBody
	public String productInfo(){
		return " admin home page ";
	}
}

之后在SecurityConfiguration里增加角色管理配置

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    //设置角色和权限
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
                .inMemoryAuthentication()
                .withUser("admin") // 管理员,同事具有 ADMIN,USER权限,可以访问所有资源
                .password("{noop}admin")
                .roles("ADMIN", "USER")
                .and()
                .withUser("user").password("{noop}user") // 普通用户,只能访问 /product/**
                .roles("USER");
    }

    //设置接口对应的权限
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/product/**").hasRole("USER")
                .antMatchers("/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
                .and()
                .formLogin().and()
                .httpBasic();
    }

}

我们还可以获取用户的信息

@RequestMapping("/info")
@ResponseBody
public String productInfo(){
	String currentUser = "";
	Object principl = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
	if(principl instanceof UserDetails) {
		currentUser = ((UserDetails)principl).getUsername();
	}else {
		currentUser = principl.toString();
	}
	return " some product info,currentUser is: "+currentUser;
}

通过数据库查询,存储用户和角色实现安全认证

实体类和repository

@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "user")
public class User implements java.io.Serializable{

	@Id
	@Column(name = "user_id")
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long userId;
	@Column(name = "user_name")
	private String userName;
	@Column
	private String password;
	@Column
	private String role;

}
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    User findUserByUserName(String userName);
}

之后在数据库插入两条数据

user_iduser_namepasswordrole
1admin$2a$10$KAIHJloiQwYHEZ05J/WrVOAxZRAHuMyUP1ibralQ4.R9FKUiFUufqROLE_ADMIN
2user$2a$10$KAIHJloiQwYHEZ05J/WrVOAxZRAHuMyUP1ibralQ4.R9FKUiFUufqROLE_USER

密码这里都是使用了BCryptPasswordEncoder 需在SecurityConfiguration中加入配置,这里的密码是123

自定义UserDetailsService

spring security在认证过程中需要查找用户,会调用UserDetailsService的loadUserByUsername方法得到一个UserDetails

@Component("userDetailsService")
public class CustomUserDetailsService implements UserDetailsService {
    @Autowired
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
        //1.查询用户
        User userFromDatabase = userRepository.findUserByUserName(userName);
        if (userFromDatabase == null) {
            //log.warn("User: {} not found", login);
            throw new UsernameNotFoundException("User " + userName + " was not found in db");
            //这里找不到必须抛异常
        }

        // 2. 设置角色
        Collection<GrantedAuthority> grantedAuthorities = new ArrayList<>();
        GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(userFromDatabase.getRole());
        grantedAuthorities.add(grantedAuthority);

        return new org.springframework.security.core.userdetails.User(
                userName, userFromDatabase.getPassword(), grantedAuthorities);
    }
}

这个方法做了2件事情,查询用户以及设置角色,通常一个用户会有多个角色,即上面的userFromDatabase.getRole()通常是一个list,所以设置角色的时候,就是for循环new 多个SimpleGrantedAuthority并设置。(本例为了简单没有设置角色表以及用户角色关联表,只在用户中增加了一个角色字段,所以grantedAuthorities只有一个)

修改SecurityConfiguration

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private CustomUserDetailsService userDetailsService;

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

    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/product/**").hasRole("USER")
                .antMatchers("/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
                .and()
                .formLogin().and()
                .httpBasic();
    }


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

}

OK了,现在admin用户能访问admin页面,而user用户只能访问product页面


hhhhh