springBoot+springSecurity权限认证

以下内容学习自微信公众号“江南一点雨”

1、引入springSecurity

<!-- spring security依赖 -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-security</artifactId>
	<version>1.5.3.RELEASE</version>
</dependency>
<!-- mysql驱动 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.17</version>
</dependency>
<!-- mybatis -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.3.5</version>
</dependency>
<!-- 数据库连接池 -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.1.10</version>
</dependency>

2、建表

2.1 user用户表

2.2 role角色表

2.3 menu菜单表

2.4 user_role用户角色关系表

2.5 role_menu菜单角色关系表


3、建立user、role、menu对应实体类,其中user类实现org.springframework.security.core.userdetails.UserDetails接口

public class User implements UserDetails {
    private Integer id;
    private String username;
    private String password;
    private boolean isEnabled;
    private List<Role> roles;

    public List<Role> getRoles() {
        return roles;
    }

    public void setRoles(List<Role> roles) {
        this.roles = roles;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public void setEnabled(boolean enabled) {
        isEnabled = enabled;
    }

    public Collection<? extends GrantedAuthority> getAuthorities() {
        List<SimpleGrantedAuthority> authority = new ArrayList<SimpleGrantedAuthority>();
        for (Role role : roles) {
            authority.add(new SimpleGrantedAuthority(role.getRoleName()));
        }
        return authority;
    }


    public boolean isAccountNonExpired() {
        return true;
    }

    public boolean isAccountNonLocked() {
        return true;
    }

    public boolean isCredentialsNonExpired() {
        return true;
    }

    public boolean isEnabled() {
        return isEnabled;
    }

4、新建UserService类实现接口org.springframework.security.core.userdetails.UserDetailsService

@Service
public class UserService implements UserDetailsService {
    @Autowired
    UserMapper userMapper;

    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userMapper.loadUserByUsername(username);
        if(user==null){
            throw new UsernameNotFoundException("用户不存在");
        }
        user.setRoles(userMapper.getRolesByUserId(user.getId()));
        return user;
    }
}

5、新建MyFilter类实现org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource,找出所有能访问当前请求路径的角色

@Component
public class MyFilter implements FilterInvocationSecurityMetadataSource {

    AntPathMatcher antPathMatcher = new AntPathMatcher();
    @Autowired
    MenuMapper menuMapper;

    public Collection<ConfigAttribute> getAttributes(Object o) throws IllegalArgumentException {
        //请求的地址路径
        String requestUrl = ((FilterInvocation) o).getRequestUrl();
        //所有菜单资源地址路径
        List<Menu> menus = menuMapper.getAllMenus();
        for (Menu menu : menus) {
            //请求路径与菜单路径匹配的上,则查看访问该菜单需要哪些角色
            if(antPathMatcher.match(menu.getMenuResource(),requestUrl)){
                List<Role> roles= menu.getRoles();
                String[] strRoles = new String[roles.size()];
                for (int i = 0; i < roles.size(); i++) {
                    strRoles[i] = roles.get(i).getRoleName();
                }
                return SecurityConfig.createList(strRoles);
            }
        }
        //其他路径
        return SecurityConfig.createList("ROLE_login");
    }

    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }

    public boolean supports(Class<?> aClass) {
        return true;
    }
}

6、新建MyAccessDecisionManager类实现org.springframework.security.access.AccessDecisionManager,根据当前用户角色,判断是否有能访问当前请求路径的

@Component
public class MyAccessDecisionManager implements AccessDecisionManager {
    public void decide(Authentication authentication, Object o, Collection<ConfigAttribute> collection) throws AccessDeniedException, InsufficientAuthenticationException {
        //collection是请求该资源需要的所有角色
        for (ConfigAttribute configAttribute : collection) {
            //登录之后就可以访问
            if(("ROLE_login").equals(configAttribute.getAttribute())){
                //匿名用户,即未登录
                if(authentication instanceof AnonymousAuthenticationToken){
                    throw new AccessDeniedException("非法请求");
                }else{
                    return;
                }
            }
            //authorities当前登录用户所拥有的角色
            Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
            for (GrantedAuthority authority : authorities) {
                //当前登录用户存在请求资源所需的角色
                if(configAttribute.getAttribute().equals(authority.getAuthority())){
                    return;
                }
            }
        }
        throw new AccessDeniedException("非法请求");
    }

    public boolean supports(ConfigAttribute configAttribute) {
        return true;
    }

    public boolean supports(Class<?> aClass) {
        return true;
    }
}

7、新建MySecurityConfig类实现org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter

@Configuration
public class MySecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    UserService userService;
    @Autowired
    MyFilter myFilter;
    @Autowired
    MyAccessDecisionManager myAccessDecisionManager;

    //密码加密方式
    @Bean
    public PasswordEncoder setPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }
    //验证用户名密码是否正确
    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http.authorizeRequests()
                .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
                    public <O extends FilterSecurityInterceptor> O postProcess(O o){
                        o.setAccessDecisionManager(myAccessDecisionManager);
                        o.setSecurityMetadataSource(myFilter);
                        return o;
                    }
                })
                .and()
                .formLogin().permitAll()
                .and()
                .csrf().disable();

    }
}

8、测试

@RestController
public class HelloController {

    @Autowired
    UserMapper userMapper;

    @GetMapping("/hello")
    public String hello(){
        return userMapper.getUserById(1).toString();
    }

    @GetMapping("/dba/hello")
    public String hellodba(){
        return "hello dba";
    }

    @GetMapping("/admin/hello")
    public String helloadmin(){
        return "hello admin";
    }

    @GetMapping("/user/hello")
    public String hellouser(){
        return "hello user";
    }
}

8.1 localhost:8888/hello      登录后所有用户都可以访问

8.2 localhost:8888/dba/hello      只有有数据库管理员角色的用户登录后才可以访问

8.3 localhost:8888/admin/hello      只有有系统管理员角色的用户登录后才可以访问

8.4 localhost:8888/user/hello      只有有普通用户角色的用户登录后才可以访问

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值