小白的springboot之旅(十一) - springboot之用户权限管理(一)

关键词:springboot,jpa,spring security,mysql

通常我们的网站都有权限控制,就像一个公司有产品、开发、运维之分,各自负责各自的业务,相互独立,有相互协作,共同完成一个任务。拥有不同权限的用户查看不同的页面,进行不同的操作。

这篇来简单的说一下使用springboot+jpa+springsecurity实现简单的用户权限管理。

角色和用户的关系通过数据库配置控制。角色可以访问的权限通过硬编码控制。

springboot是一个灵活和强大的身份验证和访问控制框架,以确保基于spring的java web应用程序的安全。它与spring mvc有很好地集成,并配备了流行的安全算法实现捆绑在一起。

1)    springscurity验证用户密码机制

首先在usernamePasswordAuthenticationFilter中来拦截登录请求,并调用AuthenticationManager。AuthenticationManager调用Provider,provider调用userDetaisService来根据username获取真实的数据库信息。 

2) 数据库设计

主要包括:用户表、角色表、用户关系表。

小白的springboot之旅(十一) - springboot之用户权限管理(一)_第1张图片

3) 添加spring security的maven依赖


   org.springframework.boot
   spring-boot-starter-security

4)编写实体

User.java实现UserDetails接口,通过getAuthorities获取用户的角色。

package com.xiaoi.document.split.security.user.entity;

import com.xiaoi.document.split.security.role.entity.Role;
import lombok.ToString;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import javax.persistence.*;
import java.util.Collection;
import java.util.List;

@Entity
@Table(name = "sys_user")
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region = "entityCache")
@ToString(includeFieldNames = true)
public class User implements UserDetails {

    @Id
    @GeneratedValue
    @Column(name = "id")
    private String id;

    @Column(name = "username")
    private String username;

    @Column(name = "password")
    private String password;

    @ManyToMany(targetEntity = Role.class, cascade = {CascadeType.REFRESH}, fetch = FetchType.EAGER)
    @JoinTable(name = "sys_role_user", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"))
    private List roles;

    public User() {
    }

    public User(String id, String username, String password) {
        this.id = id;
        this.username = username;
        this.password = password;
    }

    public String getId() {
        return id;
    }

    public void setId(String 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 getRoles() {
        return roles;
    }

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

    @Override
    public Collectionextends GrantedAuthority> getAuthorities() {
        return roles;
    }

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

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

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

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

role.java

package com.xiaoi.document.split.security.role.entity;

import com.xiaoi.document.split.security.permission.entity.Permission;
import com.xiaoi.document.split.security.user.entity.User;
import lombok.ToString;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.ManyToAny;
import org.springframework.security.core.GrantedAuthority;

import javax.persistence.*;
import java.util.List;

@Entity
@Table(name = "sys_role")
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region = "entityCache")
@ToString(includeFieldNames = true)
public class Role implements GrantedAuthority {

    @Id
    @GeneratedValue
    @Column(name = "id")
    private String id;

    @Column(name = "name")
    private String name;

    @ManyToMany(targetEntity = Permission.class, cascade = CascadeType.REFRESH, fetch = FetchType.EAGER)
    @JoinTable(name = "sys_permission_role", joinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "permission_id", referencedColumnName = "id"))
    private List permissions;

    public Role() {
    }

    public String getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List getPermissions() {
        return permissions;
    }

    public void setPermissions(List permissions) {
        this.permissions = permissions;
    }

    @Override
    public String getAuthority() {
        return name;
    }
}

5) 自定义用户验证service

UserDAO.java

package com.xiaoi.document.split.security.user.service.impl;

import com.xiaoi.document.split.security.user.dao.UserDAO;
import com.xiaoi.document.split.security.user.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

@Service(value = "customerUserService")
public class CustomerUserService implements UserDetailsService {

    @Autowired
    private UserDAO userDAO;

    @Override
    public UserDetails loadUserByUsername(String username) {
        User user = userDAO.findByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException("用户名不存在");
        }
        String pwd = new BCryptPasswordEncoder().encode(user.getPassword());
        user.setPassword(pwd);
        return user;
    }
}
CustomerService.java

package com.xiaoi.document.split.security.user.service.impl;

import com.xiaoi.document.split.security.user.dao.UserDAO;
import com.xiaoi.document.split.security.user.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

@Service(value = "customerUserService")
public class CustomerUserService implements UserDetailsService {

    @Autowired
    private UserDAO userDAO;

    @Override
    public UserDetails loadUserByUsername(String username) {
        User user = userDAO.findByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException("用户名不存在");
        }
        String pwd = new BCryptPasswordEncoder().encode(user.getPassword());
        user.setPassword(pwd);
        return user;
    }
}

controller

package com.xiaoi.document.split.security.home.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * Created by Administrator on 2018/5/24.
 */
@Controller
public class HomeCotroller {

//    @RequestMapping(value = "/", method = RequestMethod.GET)
//    String home() {
//        return "login";
//    }
//
//    @RequestMapping(value = "/login", method = RequestMethod.GET)
//    String login() {
//        return "login";
//    }

//    @RequestMapping(value = "/welcome", method = RequestMethod.GET)
//    String welcome() {
//        return "welcome";
//    }

//    @RequestMapping(value = "/loginSubmit", method = RequestMethod.GET)
//    String loginSubmit(Model model, User user) {
//        model.addAttribute("user", user);
//        return "index";
//    }

    @RequestMapping("/index")
    public String index(Model model) {
//        Msg msg =  new Msg("测试标题","测试内容","欢迎来到HOME页面,您拥有 ROLE_ADMIN 权限");
//        model.addAttribute("msg", msg);
        return "index";
    }

    @RequestMapping("/admin")
    @ResponseBody
    public String hello() {
        return "hello admin";
    }
}

6) 添加视图,配置安全策略

package com.xiaoi.document.split.security.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * WebMvcConfig 页面访问安全配置
 *
 * @Author Yuan Jingshan
 * @Date 2018-05-29
 */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/login").setViewName("login");
    }
}
package com.xiaoi.document.split.security.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;

/**
 * WebMvcSecurityConfig 页面访问安全配置
 *
 * @Author Yuan Jingshan
 * @Date 2018-05-29
 */
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private AuthorizationSecurityInterceptor authorizationSecurityInterceptor;

    //注册UserDetailsService的bean
    @Autowired
    UserDetailsService customerUserService;

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

    //安全策略
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/", "/register", "/reg", "/login").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/login")
                .failureUrl("/login?error")
                .defaultSuccessUrl("/index")
                .permitAll()
                .and()
                .logout()
                .permitAll();

        http.addFilterBefore(authorizationSecurityInterceptor, FilterSecurityInterceptor.class);
    }

    //解决静态资源被拦截的问题
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/css/**");
        web.ignoring().antMatchers("/img/**");
        web.ignoring().antMatchers("/plugins/**");
    }
}

7)前端页面

login.html

html>
xmlns:th="http://www.thymeleaf.org">

    charset="utf-8"/>
    name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    </span>springboot-demo<span style="color:#e8bf6a;">
    rel="Shortcut Icon" href="/img/logo_m.png" type="image/x-icon">
    rel="stylesheet" th:href="@{plugins/layui/css/layui.css}">
    rel="stylesheet" th:href="@{css/style.css}">

class="login">
class="layui-layout">
class="layui-body">
class="layui-row" style="margin-top: 5%;margin-bottom: 5%;">
class="layui-col-md7" style="border-bottom: 2px solid white;margin-right: 2%;letter-spacing:2px;float: right;">
class="project_name"> src="/img/logo_l.png"/> QA对知识拆分管理系统
class="layui-row">
class="layui-col-md3 layui-col-md-offset8">
class="layui-input-block" style="text-align: center;line-height: 38px;background-color: #f79647;margin-bottom:5px;font-weight: 800;color: white;letter-spacing:5px;border-radius:5px"> 用户登录
class="layui-form" th:action="@{/login}" action="/login" method="POST" style="background-color: white;padding: 10px 10px;border-radius:5px">
class="layui-form-item" style="margin-top: 10px;background-color: white;">
class="layui-input-block"> type="text" id="username" name="username" lay-verify="title" autocomplete="off" placeholder="请输入用户名" class="layui-input">
class="layui-form-item">
class="layui-input-block"> type="password" id="password" name="password" lay-verify="required" placeholder="请输入密码" autocomplete="off" class="layui-input">
id="login_div" class="layui-form-item">
class="layui-input-block">

th:if="${param.logout}" class="bg-warning">已成功注销

th:if="${param.error}" class="bg-danger">有错误,请重试

class="layui-footer">

© 贵州小爱机器人科技有限公司




   
   
   
   





恭喜您,您有 ROLE_USER 权限


你可能感兴趣的:(java,框架)