spring-security快速开发

学习完权限控制,将常用代码抽取如下,供以后开发使用

maven

<dependency>
  <groupId>org.springframework.security</groupId>
  <artifactId>spring-security-web</artifactId>
  <version>${spring.security.version}</version>
</dependency>
<dependency>
  <groupId>org.springframework.security</groupId>
  <artifactId>spring-security-config</artifactId>
  <version>${spring.security.version}</version>
</dependency>

web.xml

<filter>
    <!--
      DelegatingFilterProxy用于整合第三方框架(代理过滤器,非真正的过滤器,真正的过滤器需要在spring的配置文件)
      整合Spring Security时过滤器的名称必须为springSecurityFilterChain,
      否则会抛出NoSuchBeanDefinitionException异常
    -->
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

web层-config

springmvc.xml

  1. 主配置文件记得修改 包扫描,需要扫描到 security包

  2. 引入spring-security.xml文件

     <import resource="classpath:spring-security.xml"/>
    

spring-security.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:security="http://www.springframework.org/schema/security"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                  http://www.springframework.org/schema/beans/spring-beans.xsd
                  http://www.springframework.org/schema/mvc
                  http://www.springframework.org/schema/mvc/spring-mvc.xsd
                  http://code.alibabatech.com/schema/dubbo
                  http://code.alibabatech.com/schema/dubbo/dubbo.xsd
                  http://www.springframework.org/schema/context
                  http://www.springframework.org/schema/context/spring-context.xsd
                          http://www.springframework.org/schema/security
                          http://www.springframework.org/schema/security/spring-security.xsd">


    <!--定义哪些资源可以放行,匿名用户可以访问-->
    <security:http security="none" pattern="/js/**" />
    <security:http security="none" pattern="/css/**" />
    <security:http security="none" pattern="/img/**" />
    <security:http security="none" pattern="/plugins/**" />
    <security:http security="none" pattern="/login.html"></security:http>

    <!--开启注解方式权限控制-->
    <security:global-method-security pre-post-annotations="enabled" />

    <security:http auto-config="true" use-expressions="true">
        <!--定义哪些资源需要获得权限才能放行,只要认证通过就可以访问,非匿名用户-->
        <security:intercept-url pattern="/pages/**"  access="isAuthenticated()" />

        <!--定义表单登录信息:根据login.html页面进行设置-->
        <security:form-login login-page="/login.html"
                             username-parameter="username"
                             password-parameter="password"
                             login-processing-url="/login.do"
                             default-target-url="/pages/main.html"
                             authentication-failure-url="/login.html"
                             always-use-default-target="true"
        />

        <!--关闭csrf-->
        <security:csrf disabled="true"/>

        <!--设置页面保护策略-->
        <security:headers>
            <!--设置在页面可以通过iframe访问受保护的页面,默认为不允许访问-->
            <security:frame-options policy="SAMEORIGIN"></security:frame-options>
        </security:headers>

        <!--退出登录-->
        <security:logout logout-url="/logout.do"
                         logout-success-url="/login.html" invalidate-session="true"/>
    </security:http>

    <!--配置密码加密对象-->
    <bean id="bCryptPasswordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>

    <!--认证管理-->
    <security:authentication-manager>
        <security:authentication-provider user-service-ref="springSecurityUserService">
            <!--指定密码加密策略-->
            <security:password-encoder ref="bCryptPasswordEncoder"/>
        </security:authentication-provider>
    </security:authentication-manager>



</beans>

pojo

本模板中使用到的 POJO

User类

用户类

public class User implements Serializable{
    private Integer id; // 主键
    private Date birthday; // 生日
    private String gender; // 性别
    private String username; // 用户名,唯一
    private String password; // 密码
    private String remark; // 备注
    private String station; // 状态
    private String telephone; // 联系电话
    private Set<Role> roles = new HashSet<Role>(0);//对应角色集合
}

Role类

角色类

public class Role implements Serializable {
    private Integer id;
    private String name; // 角色名称
    private String keyword; // 角色关键字,用于权限控制
    private String description; // 描述
    private Set<User> users = new HashSet<User>(0);
    private Set<Permission> permissions = new HashSet<Permission>(0);
    private LinkedHashSet<Menu> menus = new LinkedHashSet<Menu>(0);
}

Permission类

权限类

public class Permission implements Serializable{
    private Integer id;
    private String name; // 权限名称
    private String keyword; // 权限关键字,用于权限控制
    private String description; // 描述
    private Set<Role> roles = new HashSet<Role>(0);
}

web-java

security层

创建com.xxx.security包,与com.xxx.controller同级别

package com.xxx.security;

import com.alibaba.dubbo.config.annotation.Reference;
import com.xxx.pojo.Permission;
import com.xxx.pojo.Role;
import com.xxx.service.UserService;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
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.Component;

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


@Component
public class SpringSecurityUserService implements UserDetailsService {

    @Reference //注意:此处要通过dubbo远程调用用户服务
    private UserService userService;

    //根据用户名查询用户信息
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //远程调用用户服务,根据用户名查询用户信息
        // 这里写全类名为了防止自定义的 User 类与Security中使用的 User 类冲突
        com.xxx.pojo.User user = userService.findUserByUsername(username);
        if(user == null){
            //用户名不存在,抛出异常UsernameNotFoundException 
            return null;
        }
        List<GrantedAuthority> list = new ArrayList<GrantedAuthority>();
        Set<Role> roles = user.getRoles();
        for(Role role : roles){
            Set<Permission> permissions = role.getPermissions();
            for(Permission permission : permissions){
                //授权
                list.add(new SimpleGrantedAuthority(permission.getKeyword()));
            }
        }
        /**
         * User()
         * 1:指定用户名
         * 2:指定密码(SpringSecurity会自动对密码进行校验)
         * 3:传递授予的角色和权限
         */
        UserDetails userDetails = new User(username,user.getPassword(),list);
        return userDetails;
    }
}

XXX.controller

在Controller的方法上加入权限控制注解@PreAuthorize("hasAuthority('权限名')")

 @RequestMapping("/edit")
    @PreAuthorize("hasAuthority('TRAVELITEM_EDIT')")//权限校验
    public Result edit(@RequestBody TravelItem travelItem){
        travelItemService.edit(travelItem);
        return new Result(true,MessageConstant.EDIT_TRAVELITEM_SUCCESS);
    }

html页面

以删除请求为例,处理权限错误的 ajax 请求

// 删除
handleDelete(row) {
    // alert(row.id);
    this.$confirm("确认删除当前选中记录吗?","提示",{type:'warning'}).then(()=>{
        //点击确定按钮时只需此处代码
        // alert('用户点击的是确定按钮');
        axios.get("/travelItem/delete.do?id=" + row.id).then((res)=> {
            if(res.data.flag){
                //删除成功
                this.$message({
                    message: res.data.message,
                    type: 'success'
                });
                //调用分页,获取最新分页数据
                this.findPage();
            }else{
                //删除失败
                this.$message.error(res.data.message);
            }
        }).catch((error)=>{
            this.showMessage(error);
        });
    }).catch(()=> {
        //点击取消按钮执行此代码
        this.$message('操作已取消');
    });
},
//权限不足提示
showMessage(r){
    if(r == 'Error: Request failed with status code 403'){
        //权限不足
        this.$message.error('无访问权限');
        return;
    }else{
        this.$message.error('未知错误');
        return;
    }
}
原文地址:https://www.cnblogs.com/tianwenxin/p/15021537.html