springboot+security restful权限控制官方推荐(五)

继前几篇博客将用户、角色、权限信息都存在数据,实现管理权限到请求方法级别。感觉那种实现方式比较鸡肋,不太实用。所以今天说一下,官方推荐的注解方式控制权限到请求方法级别的实现。

官方推荐的方法是将用户、角色信息存在数据库,而角色和权限的对应关系,通过注解的方式写死在controller上。

废话不多说,上代码;

本文代码是基于博客 springboot+mybatis+SpringSecurity 实现用户角色数据库管理(一)
的代码修改而来

1. 数据库设计

这里写图片描述

insert into SYS_USER (id,username, password) values (1,'admin', '$2a$10$YwbP2rm18bOWOrkJHybp5uTRHCpn5Rk8rGT6fogf0KdtNY7jzmebu');
insert into SYS_USER (id,username, password) values (2,'abel', '$2a$10$/h0hVDo3A78lEHhsIckGz.nfXGgUFx2yB4bfy6o15RZi8VlZqt.PK');

insert into SYS_ROLE(id,name) values(1,'ROLE_ADMIN');
insert into SYS_ROLE(id,name) values(2,'ROLE_USER');

2. 修改WebSecurityConfig 文件

此处使用了 BCryptPasswordEncoder 密码加密

使用了httpBasic 认证 : springSecurity 之 http Basic认证 (四)

package com.us.example.config;

import com.us.example.security.CustomUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

/**
 * Created by yangyibo on 17/1/18.
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)// 控制权限注解
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
     private  CustomUserService customUserService;


    @Autowired
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(customUserService).passwordEncoder(new BCryptPasswordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .authorizeRequests()
                .antMatchers("/users/**")
                .authenticated()
                .antMatchers(HttpMethod.POST)
                .authenticated()
                .antMatchers(HttpMethod.PUT)
                .authenticated()
                .antMatchers(HttpMethod.DELETE)
                .authenticated()
                .antMatchers("/**")
                .permitAll()
                .and()
                .sessionManagement()
                .and()
                .httpBasic();
    }
}

3. 修改SysUser 类实现 UserDetails接口

package com.us.example.domain;

import com.fasterxml.jackson.annotation.JsonIgnore;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.Collection;
import java.util.List;

/**
 * Created by yangyibo on 17/1/17.
 */

public class SysUser implements UserDetails {  // implements UserDetails 用于登录时 @AuthenticationPrincipal 标签取值
    private Integer id;
    private String username;
    @JsonIgnore
    private String password;
    private String rawPassword;
    @JsonIgnore
    private List<SysRole> roles;
    private List<? extends GrantedAuthority> authorities;


    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 List<SysRole> getRoles() {
        return roles;
    }

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

    public String getRawPassword() {
        return rawPassword;
    }

    public void setRawPassword(String rawPassword) {
        this.rawPassword = rawPassword;
    }


    @JsonIgnore
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @JsonIgnore
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @JsonIgnore
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }


    @JsonIgnore
    @Override
    public boolean isEnabled() {
        return true;
    }

    @JsonIgnore
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return authorities;
    }

    public void setGrantedAuthorities(List<? extends GrantedAuthority> authorities) {
        this.authorities = authorities;
    }
}

4. 修改 CustomUserService 类

package com.us.example.security;

import com.us.example.dao.UserDao;
import com.us.example.domain.SysRole;
import com.us.example.domain.SysUser;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by yangyibo on 17/1/18.
 */
@Service
public class CustomUserService implements UserDetailsService { //自定义UserDetailsService 接口

    @Autowired
    UserDao userDao;
    private static final org.slf4j.Logger logger = LoggerFactory.getLogger(CustomUserService.class);

    @Override
    public UserDetails loadUserByUsername(String username) { //重写loadUserByUsername 方法获得 userdetails 类型用户

        SysUser user = userDao.findByUserName(username);
        if(user == null){
            throw new UsernameNotFoundException("用户名不存在");
        }
        List<SimpleGrantedAuthority> authorities = new ArrayList<>();
        //用于添加用户的权限。只要把用户权限添加到authorities 就万事大吉。
        for(SysRole role:user.getRoles())
        {
            authorities.add(new SimpleGrantedAuthority(role.getName()));
            logger.info("loadUserByUsername: " + user);
        }
        user.setGrantedAuthorities(authorities); //用于登录时 @AuthenticationPrincipal 标签取值
        return user;
    }
}

5. 添加登录controller

新建LoginController

package com.us.example.controller;

import com.us.example.domain.SysUser;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;


/**
 * Created by yangyibo on 17/3/1.
 */
@RestController
public class LoginController {

    @RequestMapping(value = "/login")
    @ResponseBody
    public Object login(@AuthenticationPrincipal SysUser loginedUser, @RequestParam(name = "logout", required = false) String logout) {
        if (logout != null) {
            return null;
        }
        if (loginedUser != null) {
            return loginedUser;
        }
        return null;
    }
}

6. 修改 HomeController 添加权限控制

package com.us.example.controller;

import com.us.example.domain.SysUser;
import com.us.example.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * Created by yangyibo on 17/1/18.
 */
@Controller
@RequestMapping("/users")
public class HomeController {
    @Autowired
    UserService userService;

    @RequestMapping(method = RequestMethod.GET)
    @ResponseBody
    public String getUsers() {
        return "getUsers";
    }

    @Secured({"ROLE_ADMIN","ROLE_USER"})//此方法只允许 ROLE_ADMIN 和ROLE_USER 角色 访问
    @RequestMapping(method = RequestMethod.POST)
    @ResponseBody
    public Object save(@RequestBody SysUser user) {
        return  userService.create(user);
    }


    @Secured("ROLE_ADMIN")//此方法只允许 ROLE_ADMIN 角色访问
    @RequestMapping(method = RequestMethod.PUT)
    @ResponseBody
    public String update() {
        return "updateUser";
    }

    @Secured("ROLE_ADMIN")//此方法只允许 ROLE_ADMIN 角色访问
    @RequestMapping(method = RequestMethod.DELETE)
    @ResponseBody
    public String delete() {
        return "deleteUser";
    }

}

7. 测试

使用admin 登录

关于登录方式请移步: springSecurity 之 http Basic认证 (四)

可以访问 /users 路径下的get、post、put、delete 四个请求方法

使用abel 登录
可以访问 /users 路径下的get、post 两个请求方法
访问 put、delete 方法会抛403 没有权限异常

本文源码:https://github.com/527515025/springBoot

  • 7
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 23
    评论
评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值