旅游后台项目——SSM权限操作(Spring Security)

SSM权限操作

数据库与表结构

用户表

角色表

用户与角色之间是多对多关系,通过user_role表来描述其关联,在实体类中User中存在List,在Role中有List。而角色与权限之间也存在关系。

资源权限表

权限资源与角色是多对多关系,使用role_permission表来描述。在实体类Permission中存在List。在Role类中有List

Spring Security概述

Spring Security介绍

Spring Security 的前身是 Acegi Security ,是 Spring 项目组中用来提供安全认证服务的框架。(https://projects.spring.io/spring-security/) Spring Security 为基于J2EE企业应用软件提供了全面安全服务。特别是使用领先的J2EE解决方案-Spring框架开发的企业软件项目。人们使用Spring Security有很多种原因,不过通常吸引他们的是在J2EE Servlet规范或EJB规范中找不到典型企业应用场景的解决方案。 特别要指出的是他们不能再WAR 或 EAR 级别进行移植。这样,如果你更换服务器环境,就要,在新的目标环境进行大量的工作,对你的应用系统进行重新配 置安全。使用Spring Security 解决了这些问题,也为你提供很多有用的,完全可以指定的其他安全特性。 安全包括两个主要操作。

  • “认证”,是为用户建立一个他所声明的主体。主题一般式指用户,设备或可以在你系统中执行动作的其他系统。
  • “授权”指的是一个用户能否在你的应用中执行某个操作,在到达授权判断之前,身份的主题已经由 身份验证过程建立了。

这些概念是通用的,不是Spring Security特有的。在身份验证层面,Spring Security广泛支持各种身份验证模式,这些验证模型绝大多数都由第三方提供,或则正在开发的有关标准机构提供的,例如 Internet Engineering TaskForce.作为补充,Spring Security 也提供了自己的一套验证功能。

Spring Security 目前支持认证一体化如下认证技术: HTTP BASIC authentication headers (一个基于IEFT RFC 的标准) HTTP Digest authentication headers (一个基于IEFT RFC 的标准) HTTP X.509 client certifificate exchange(一个基于IEFT RFC 的标准) LDAP (一个非常常见的跨平台认证需要做法,特别是在大环境) Form-basedauthentication (提供简单用户接口的需求) OpenID authentication Computer Associates Siteminder JA-SIGCentral Authentication Service (CAS,这是一个流行的开源单点登录系统) Transparent authentication context propagation for Remote Method Invocation and HttpInvoker (一个Spring远程调用协议)

Maven依赖

<!--  权限  -->    <dependency>      <groupId>org.springframework.security</groupId>      <artifactId>spring-security-web</artifactId>      <version>5.0.1.RELEASE</version>    </dependency>    <dependency>      <groupId>org.springframework.security</groupId>      <artifactId>spring-security-config</artifactId>      <version>5.0.1.RELEASE</version>    </dependency>    <dependency>      <groupId>org.springframework.security</groupId>      <artifactId>spring-security-core</artifactId>      <version>5.0.1.RELEASE</version>    </dependency>    <dependency>      <groupId>org.springframework.security</groupId>      <artifactId>spring-security-taglibs</artifactId>      <version>5.0.1.RELEASE</version>    </dependency>

Spring Security快速入门

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>spring_security_demo</groupId> <artifactId>SpringSecurity_quickStart</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <properties> <spring.version>5.0.2.RELEASE</spring.version> <spring.security.version>5.0.1.RELEASE</spring.security.version> </properties> <dependencies>     <dependency>         <groupId>org.springframework</groupId>         <artifactId>spring-core</artifactId>         <version>${spring.version}</version>     </dependency>     <dependency>         <groupId>org.springframework</groupId>         <artifactId>spring-web</artifactId>         <version>${spring.version}</version>     </dependency>     <dependency>         <groupId>org.springframework</groupId>         <artifactId>spring-webmvc</artifactId>         <version>${spring.version}</version>     </dependency>     <dependency>         <groupId>org.springframework</groupId>         <artifactId>spring-context-support</artifactId>         <version>${spring.version}</version>     </dependency>     <dependency>         <groupId>org.springframework</groupId>         <artifactId>spring-test</artifactId>         <version>${spring.version}</version>     </dependency>     <dependency>         <groupId>org.springframework</groupId>         <artifactId>spring-jdbc</artifactId>         <version>${spring.version}</version>     </dependency>     <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>     <dependency>         <groupId>javax.servlet</groupId>         <artifactId>javax.servlet-api</artifactId>         <version>3.1.0</version>         <scope>provided</scope>     </dependency> </dependencies> <build>     <plugins>         <!-- java编译插件 -->         <plugin>             <groupId>org.apache.maven.plugins</groupId>             <artifactId>maven-compiler-plugin</artifactId>             <version>3.2</version>             <configuration>                 <source>1.8</source>                 <target>1.8</target>                 <encoding>UTF-8</encoding>             </configuration>         </plugin>      <plugin>             <groupId>org.apache.tomcat.maven</groupId>             <artifactId>tomcat7-maven-plugin</artifactId>             <configuration>                 <!-- 指定端口 -->                 <port>8080</port>                 <!-- 请求路径 -->                 <path>/</path>             </configuration>         </plugin>     </plugins> </build></project>     

web.xml

<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-security.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <filter> <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>

spring security配置

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:security="http://www.springframework.org/schema/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans.xsd  http://www.springframework.org/schema/security  http://www.springframework.org/schema/security/spring-security.xsd"> <security:http auto-config="true" use-expressions="false"> <!-- intercept-url定义一个过滤规则 pattern表示对哪些url进行权限控制,ccess属性表示在请求对应的URL时需要什么权限,默认配置时它应该是一个以逗号分隔的角色列表,请求的用户只需拥有其中的一个角色就能成功访问对应的URL -->     <security:intercept-url pattern="/**" access="ROLE_USER" />     <!-- auto-config配置后,不需要在配置下面信息 <security:form-login /> 定义登录表单信息        <security:http-basic/> <security:logout /> --> </security:http>    <security:authentication-manager>         <security:authentication-provider>              <security:user-service>                   <security:user name="user" password="{noop}user"                                 authorities="ROLE_USER" />                   <security:user name="admin" password="{noop}admin"                                 authorities="ROLE_ADMIN" />              </security:user-service>         </security:authentication-provider>     </security:authentication-manager></beans>

我们在webapp下创建一个index.html页面,在页面中任意写些内容。

当我们访问index.html页面时发现会弹出登录窗口,可能你会奇怪,我们没有建立下面的登录页面,为什么SpringSecurity会跳到上面的登录页面呢?这是我们设置http的auto-confifig=”true”时Spring Security自动为我们生成的。

使用自定义页面

spring-security.xml配置

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:security="http://www.springframework.org/schema/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd"> <!-- 配置不过滤的资源(静态资源及登录相关) --> <security:http security="none" pattern="/login.html" /> <security:http security="none" pattern="/failer.html" /> <security:http auto-config="true" use-expressions="false">     <!-- 配置资料连接,表示任意路径都需要ROLE_USER权限 -->     <security:intercept-url pattern="/**" access="ROLE_USER" />     <!-- 自定义登陆页面,login-page 自定义登陆页面 authentication-failure-url 用户权限校验失败之后才会跳转到这个页面,如果数据库中没有这个用户则不会跳转到这个页面。default-target-url 登陆成功后跳转的页面。 注:登陆页面用户名固定 username,密码password,action:login -->     <security:form-login login-page="/login.html"     login-processing-url="/login" username-parameter="username"     password-parameter="password" authentication-failure-url="/failer.html"     default-target-url="/success.html"      />     <!-- 登出, invalidate-session 是否删除session logout-url:登出处理链接 logout-successurl:登出成功页面     注:登出操作 只需要链接到 logout即可登出当前用户 -->     <security:logout invalidate-session="true" logout-url="/logout"     logout-success-url="/login.jsp" />     <!-- 关闭CSRF,默认是开启的 -->     <security:csrf disabled="true" /> </security:http> <security:authentication-manager>     <security:authentication-provider>         <security:user-service>             <security:user name="user" password="{noop}user"             authorities="ROLE_USER" />             <security:user name="admin" password="{noop}admin"             authorities="ROLE_ADMIN" />         </security:user-service>     </security:authentication-provider> </security:authentication-manager></beans>

login.html

 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body>     <form action="login" method="post">         <table>             <tr>             <td>用户名:</td>             <td>                 <input type="text" name="username" /></td>             </tr>             <tr>             <td>密码:</td>             <td>                 <input type="password" name="password" /></td>             </tr>             <tr>             <td colspan="2" align="center">                 <input type="submit" value="登录" />              <input type="reset" value="重置" /></td>             </tr>         </table>     </form> </body> </html>

success.html

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> success html<br>     <a href="logout">退出</a> </body> </html>

failer.html

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body>登录失败 </body> </html>

Spring Security使用数据库认证

在Spring Security中如果想要使用数据进行认证操作,有很多种操作方式,这里我们介绍使用UserDetails、UserDetailsService来完成操作。

UserDetails

public interface UserDetails extends Serializable {      Collection<? extends GrantedAuthority> getAuthorities();     String getPassword();      String getUsername();      boolean isAccountNonExpired();      boolean isAccountNonLocked();     boolean isCredentialsNonExpired();     boolean isEnabled();}

UserDetails是一个接口,我们可以认为UserDetails作用是于封装当前进行认证的用户信息,但由于其是一个接口,所以我们可以对其进行实现,也可以使用Spring Security提供的一个UserDetails的实现类User来完成操作

User

public class User implements UserDetails, CredentialsContainer {     private String password;     private final String username;     private final Set<GrantedAuthority> authorities;     private final boolean accountNonExpired; //帐户是否过期     private final boolean accountNonLocked; //帐户是否锁定     private final boolean credentialsNonExpired; //认证是否过期     private final boolean enabled; //帐户是否可用}

UserDetailsService

public interface UserDetailsService { UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;}

上面将UserDetails与UserDetailsService做了一个简单的介绍,那么我们具体如何完成Spring Security的数据库认证操作哪,我们通过用户管理中用户登录来完成Spring Security的认证操作。

用户管理

用户登录

spring security的配置

 <!-- 切换成数据库中的用户名和密码 -->    <security:authentication-manager>        <security:authentication-provider user-service-ref="userService">            <security:password-encoder ref="passwordEncoder"/>        </security:authentication-provider>    </security:authentication-manager>

Service

@Service("userService")@Transactionalpublic class UserServiceImpl implements IUserService {     @Autowired     private IUserDao userDao;     @Override     public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {         UserInfo userInfo = userDao.findByUsername(username);         List<Role> roles = userInfo.getRoles();         List<SimpleGrantedAuthority> authoritys = getAuthority(roles);         User user = new User(userInfo.getUsername(), "{noop}"   userInfo.getPassword(),         userInfo.getStatus() == 0 ? false : true, true, true, true, authoritys);         return user;     }         private List<SimpleGrantedAuthority> getAuthority(List<Role> roles) {         List<SimpleGrantedAuthority> authoritys = new ArrayList();         for (Role role : roles) {         authoritys.add(new SimpleGrantedAuthority(role.getRoleName()));         }         return authoritys;     }}

UserDao

public interface IUserDao {     @Select("select * from user where id=#{id}")     public UserInfo findById(Long id) throws Exception;         @Select("select * from user where username=#{username}")     @Results({         @Result(id = true, property = "id", column = "id"),         @Result(column = "username", property = "username"),         @Result(column = "email", property = "email"),          @Result(column = "password", property = "password"),         @Result(column = "phoneNum", property = "phoneNum"),          @Result(column = "status", property = "status"),         @Result(column = "id", property = "roles", javaType = List.class, many =          @Many(select = "com.itheima.ssm.dao.IRoleDao.findRoleByUserId")) })     public UserInfo findByUsername(String username); }

用户退出

使用spring security完成用户退出,非常简单

配置

<security:logout invalidate-session="true" logout-url="/logout.do" logout-success-url="/login.jsp" />

页面中

<a href="${pageContext.request.contextPath}/logout.do" class="btn btn-default btn-flat">注销</a>

用户查询

UserController

@Controller@RequestMapping("/user")public class UserControlller {      @RequestMapping("/findAll.do")     public ModelAndView findAll() throws Exception {      List<UserInfo> users = userService.findAll();         ModelAndView mv = new ModelAndView();         mv.addObject("userlist", users);         mv.setViewName("user-list");         return mv;     }}

Dao

@Select("select * from user") public List<UserInfo> findAll();

用户添加

UserController

@Controller@RequestMapping("/user")public class UserControlller {     @Autowired     private IUserService userService;     @RequestMapping("/save.do")     public String save(UserInfo user) throws Exception {         userService.save(user);         return "redirect:findAll.do";     } }

Service

@Service("userService")@Transactionalpublic class UserServiceImpl implements IUserService {     @Autowired     private IUserDao userDao;     @Autowired     private PasswordEncoder passwordEncoder;     @Override     public void save(UserInfo user) throws Exception {         user.setPassword(passwordEncoder.encode(user.getPassword()));         userDao.save(user);     }}

前期我们的用户密码没有加密,现在添加用户时,我们需要对用户密码进行加密

<!-- 配置加密类 -->    <bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>

Dao

@Insert("insert into user(email,username,password,phoneNum,status) value(#{email},#{username},#{password},#{phoneNum},#{status})") public void save(UserInfo user) throws Exception;

用户详情

用户详情页面user-show.jsp

注意:需要添加js

$("#collapse-table").treetable({ expandable : true });

UserController

@Controller @RequestMapping("/user") public class UserControlller {     @Autowired     private IUserService userService;    @RequestMapping("/findById.do")    public ModelAndView findById(@RequestParam(name = "id", required = true) String id) throws Exception {        Users user = userService.findById(id);        ModelAndView mv = new ModelAndView();        mv.addObject("user", user);        mv.setViewName("user-show");        return mv;    }}

Dao

@Select("select * from users where id=#{id}")@Results({ @Result(id = true, property = "id", column = "id"), @Result(column = "username", property = "username"),        @Result(column = "email", property = "email"), @Result(column = "password", property = "password"),        @Result(column = "phoneNum", property = "phoneNum"), @Result(column = "status", property = "status"),        @Result(column = "id", property = "roles", javaType = List.class, many =        @Many(select = "com.sibd.travel.mapper.RoleMapper.findRoleByUserId")) })Users findById(String id);
@Select("select * from role where id in( select roleId from user_role where userId=#{userId})")     @Results(     {         @Result(id=true,column="id",property="id"),         @Result(column="roleName",property="roleName"),         @Result(column="roleDesc",property="roleDesc"),   @Result(column="id",property="permissions",javaType=List.class,many=@Many(select="com.itheima.ssm.dao.IPermissionDao.findByRoleId"))     }) public List<Role> findRoleByUserId(Long userId);

我们需要将用户的所有角色及权限查询出来所以需要调用IRoleDao中的findRoleByUserId,而在IRoleDao中需要调用IPermissionDao的findByRoleId

@Select("select * from permission where id in (select permissionId from role_permission where roleId=#{roleId})") public List<Permission> findByRoleId(Long roleId);

角色管理

角色查询

RoleControlller

@RequestMapping("/role") @Controller public class RoleController {     @Autowired     private IRoleService roleService;     @RequestMapping("/findAll.do")     public ModelAndView findAll() throws Exception {         List<Role> roleList = roleService.findAll();         ModelAndView mv = new ModelAndView();         mv.addObject("roleList", roleList);         mv.setViewName("role-list");         return mv;     } }

Dao

@Select("select * from role") public List<Role> findAll();

角色添加

RoleController

@RequestMapping("/role") @Controller public class RoleController {     @Autowired     private IRoleService roleService;     @RequestMapping("/save.do")     public String save(Role role) {         roleService.save(role);         return "redirect:findAll.do";     } }

Dao

@Insert("insert into role(roleName,roleDesc) value(#{roleName},#{roleDesc})") public void save(Role role);

资源权限管理

资源权限查询

PermissionController

@RequestMapping("/permission") @Controller public class PermissionController {@Autowired     private IPermissionService permissionService;     @RequestMapping("/findAll.do")     public ModelAndView findAll() throws Exception {         List<Permission> permissionList = permissionService.findAll();         ModelAndView mv = new ModelAndView();         mv.addObject("permissionList", permissionList);         mv.setViewName("permission-list");         return mv;     } }

Dao

@Select("select * from permission") public List<Permission> findAll();

资源权限添加

PermissionController

@RequestMapping("/permission") @Controller public class PermissionController {     @Autowired     private IPermissionService permissionService;     @RequestMapping("/save.do")     public String save(Permission p) throws Exception {         permissionService.save(p);         return "redirect:findAll.do";     } }

Dao

@Insert("insert into permission(permissionName,url) value(#{permissionName},#{url})") public void save(Permission p);

权限关联与控制

用户角色关联

用户与角色之间是多对多关系,我们要建立它们之间的关系,只需要在中间表user_role插入数据即可。

用户角色关联相关页面

在user-list.jsp页面上添加链接

<a href="${pageContext.request.contextPath}/user/findUserByIdAndAllRole.do?id=${user.id}" class="btn bg-olive btn-xs">添加角色</a>

展示可以添加角色的页面user-role-add.jsp

UserController

findUserByIdAndAllRole(Long id)方法

此方法用于查找要操作的用户及可以添加的角色,参数是要操作的用户id

@RequestMapping("/findUserByIdAndAllRole.do") public ModelAndView findUserByIdAndAllRole(Long id) throws Exception {     UserInfo user = userService.findById(id);     List<Role> roleList = roleService.findOtherRole(id);     ModelAndView mv = new ModelAndView();     mv.addObject("user", user);     mv.addObject("roleList", roleList);     mv.setViewName("user-role-add");     return mv; }

调用UserService的findById方法获取要操作的User

调用RoleService的findOtherRole方法用于获取可以添加的角色信息

  • addRoleToUser(Long userId,Long[] ids)方法

这些方法用于在用户与角色之间建立关系,参数userId代表要操作的用户id,参数ids代表的是角色id数组

@RequestMapping("/addRoleToUser.do") public String addRoleToUser(Long userId, Long[] ids) throws Exception {     userService.addRoleToUser(userId,ids);     return "redirect:findAll.do"; }

Dao

//用于查找可以添加的角色@Select("select * from role where id not in( select roleId from user_role where userId=#{id})") public List<Role> findOtherRole(Long id);
//用于添加用户与角色关系@Insert("insert into user_role(userId,roleId) value(#{userId},#{roleId})") public void addRoleToUser(@Param("userId") Long userId, @Param("roleId") Long roleId);

角色权限关联

角色与权限之间是多对多关系,我们要建立它们之间的关系,只需要在中间表role_permission插入数据即可。

角色权限关联相关页面

在role-list.jsp页面上添加链接

<a href="${pageContext.request.contextPath}/role/findRoleByIdAndAllPermission.do?id=${role.id}" class="btn bg-olive btn-xs">添加权限</a>

展示可以添加权限的页面roe-permission-add.jsp

RoleController

  • findRoleByIdAndAllPermission(Long roleId)方法

此方法用于查找要操作的角色及可以添加的权限,参数是要操作的角色id

@RequestMapping("/findRoleByIdAndAllPermission.do") public ModelAndView findRoleByIdAndAllPermission(@RequestParam(name = "id", required = true) Long roleid) throws Exception {     ModelAndView mv = new ModelAndView();     Role role = roleService.findById(roleid);     mv.addObject("role", role);     List<Permission> permissionList =     permissionService.findOtherPermission(roleid);     mv.addObject("permissionList", permissionList);     mv.setViewName("role-permission-add");     return mv; }

调用RoleService的findById方法获取要操作的Role

调用PermissionService的findOtherPermission方法用于获取可以添加的权限信息

  • addPermissionToRole(Long roleId,Long[] ids)方法

些方法用于在角色与权限之间建立关系,参数roleId代表要操作的角色id,参数permissionIds代表的是权限id数组

@RequestMapping("/addPermissionToRole.do") public String addPermissionToRole(@RequestParam(name = "roleId") Long roleId, @RequestParam(name = "ids") Long[] permissionIds) throws Exception {     roleService.addPermissionToRole(roleId, permissionIds);     return "redirect:findAll.do"; }

Dao

//用于查找可以添加的权限@Select("select * from permission where id not in (select permissionId from role_permission where roleId=#{roleId})") public List<Permission> findOtherPermission(Long roleid);
//用于绑定角色与权限的关系@Insert("insert into role_permission (roleId,permissionId) value (#{roleId},#{permissionId})") public void addPermissionToRole(@Param("roleId") Long roleId,@Param("permissionId") Long permissionId);

服务器端方法级权限控制

在服务器端我们可以通过Spring security提供的注解对方法来进行权限控制。Spring Security在方法的权限控制上支持三种类型的注解,JSR-250注解、@Secured注解和支持表达式的注解,这三种注解默认都是没有启用的,需要单独通过global-method-security元素的对应属性进行启用

开启注解使用

  • 配置文件
<security:global-method-security jsr250-annotations=*"enabled"*/> <security:global-method-security secured-annotations=*"enabled"*/> <security:global-method-security pre-post-annotations=*"disabled"*/>
  • 注解开启

@EnableGlobalMethodSecurity :Spring Security默认是禁用注解的,要想开启注解,需要在继承

WebSecurityConfigurerAdapter的类上加@EnableGlobalMethodSecurity注解,并在该类中将

AuthenticationManager定义为Bean。

@Configuration@EnableWebSecurity@EnableGlobalMethodSecurity(jsr250Enabled = true, prePostEnabled = true, securedEnabled = true)public class WebSecurityConfig extends WebSecurityConfigurerAdapter {}

JSR-250注解

  • @RolesAllowed表示访问对应方法时所应该具有的角色

  • 示例:@RolesAllowed({"USER", "ADMIN"}) 该方法只要具有"USER", "ADMIN"任意一种权限就可以访问。这里可以省略前缀ROLE_,实际的权限可能是ROLE_ADMIN
  • @PermitAll表示允许所有的角色进行访问,也就是说不进行权限控制

  • @DenyAll是和PermitAll相反的,表示无论什么角色都不能访问

支持表达式的注解

  • @PreAuthorize 在方法调用之前,基于表达式的计算结果来限制对方法的访问
示例:@PreAuthorize("#userId == authentication.principal.userId or hasAuthority(‘ADMIN’)") void changePassword(@P("userId") long userId ){ } 这里表示在changePassword方法执行之前,判断方法参数userId的值是否等于principal中保存的当前用户的userId,或者当前用户是否具有ROLE_ADMIN权限,两种符合其一,就可以访问该方法。
  • 常见内置表达式https://docs.spring.io/spring-security/site/docs/4.0.1.RELEASE/reference/htmlsingle/#el-common-built-in
  • @PostAuthorize 允许方法调用,但是如果表达式计算结果为false,将抛出一个安全性异常
示例:@PostAuthorize User getUser("returnObject.userId == authentication.principal.userId or hasPermission(returnObject, 'ADMIN')");
  • @PostFilter 允许方法调用,但必须按照表达式来过滤方法的结果

  • @PreFilter 允许方法调用,但必须在进入方法之前过滤输入值

@Secured注解

  • @Secured注解标注的方法进行权限控制的支持,其值默认为disabled。
示例: @Secured("IS_AUTHENTICATED_ANONYMOUSLY")  public Account readAccount(Long id);  @Secured("ROLE_TELLER")

@Secured注解是用来定义业务方法的安全配置。在需要安全[角色/权限等]的方法上指定 @Secured,并且只有那些角色/权限的用户才可以调用该方法。

@Secured缺点(限制)就是不支持Spring EL表达式。不够灵活。并且指定的角色必须以ROLE_开头,不可省略。该注解功能要简单的多,默认情况下只能基于角色(默认需要带前缀 ROLE_)集合来进行访问控制决策。该注解的机制是只要其声明的角色集合(value)中包含当前用户持有的任一角色就可以访问。也就是 用户的角色集合和 @Secured 注解的角色集合要存在非空的交集。 不支持使用 SpEL 表达式进行决策。

页面端标签控制权限

在jsp页面中我们可以使用spring security提供的权限标签来进行权限控制

maven导入

<dependency>      <groupId>org.springframework.security</groupId>      <artifactId>spring-security-taglibs</artifactId>      <version>version</version> </dependency>

页面导入

<%@taglib uri="http://www.springframework.org/security/tags" prefix="security"%>

常用标签

在jsp中我们可以使用以下三种标签,其中authentication代表的是当前认证对象,可以获取当前认证对象信息,例如用户名。其它两个标签我们可以用于权限控制

authentication

authentication代表的是当前认证对象,可以获取当前认证对象信息

<security:authentication property="" htmlEscape="" scope="" var=""/>
  • property: 只允许指定Authentication所拥有的属性,可以进行属性的级联获取,如“principle.username”,不允许直接通过方法进行调用
  • htmlEscape:表示是否需要将html进行转义。默认为true。
  • scope:与var属性一起使用,用于指定存放获取的结果的属性名的作用范围,默认我pageContext。Jsp中拥有的作用范围都进行进行指定
  • var: 用于指定一个属性名,这样当获取到了authentication的相关信息后会将其以var指定的属性名进行存放,默认是存放在pageConext中

authorize

authorize是用来判断普通权限的,通过判断用户是否具有对应的权限而控制其所包含内容的显示

<security:authorize access="" method="" url="" var=""></security:authorize>
  • access: 需要使用表达式来判断权限,当表达式的返回结果为true时表示拥有对应的权限
  • method:method属性是配合url属性一起使用的,表示用户应当具有指定url指定method访问的权限,method的默认值为GET,可选值为http请求的7种方法
  • url:url表示如果用户拥有访问指定url的权限即表示可以显示authorize标签包含的内容
  • var:用于指定将权限鉴定的结果存放在pageContext的哪个属性中

accesscontrollist

accesscontrollist标签是用于鉴定ACL权限的。其一共定义了三个属性:hasPermission、domainObject和var,其中前两个是必须指定的

<security:accesscontrollist hasPermission="" domainObject="" var=""></security:accesscontrollist>
  • hasPermission:hasPermission属性用于指定以逗号分隔的权限列表
  • domainObject:domainObject用于指定对应的域对象
  • var:var则是用以将鉴定的结果以指定的属性名存入pageContext中,以供同一页面的其它地方使用

来源:https://www.icode9.com/content-4-860301.html

(0)

相关推荐