springsecurity整合springboot實現簡單認證授權


主要用到了springboot,springsecurity,mybatis,jsp

1. 創建項目

使用idea中的spring工具創建項目創建時勾選springboot start webspringsecurity最終生成的pom.xml文件如下

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>springboot_security_jsp</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <name>springboot_security_jsp</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-taglibs</artifactId>
            <version>5.2.1.RELEASE</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.48</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/tk.mybatis/mapper-spring-boot-starter -->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring-boot-starter</artifactId>
            <version>2.1.5</version>
        </dependency>


        <!--        整合jsp需要如下兩個包-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
            <version>9.0.30</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>javax.annotation</groupId>
            <artifactId>jsr250-api</artifactId>
            <version>1.0</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

2. 數據庫表字段信息

CREATE TABLE `persistent_logins` (
  `username` varchar(64) NOT NULL,
  `series` varchar(64) NOT NULL,
  `token` varchar(64) NOT NULL,
  `last_used` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`series`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE `sys_permission` (
  `ID` int(11) NOT NULL AUTO_INCREMENT COMMENT '編號',
  `permission_NAME` varchar(30) DEFAULT NULL COMMENT '菜單名稱',
  `permission_url` varchar(100) DEFAULT NULL COMMENT '菜單地址',
  `parent_id` int(11) NOT NULL DEFAULT '0' COMMENT '父菜單id',
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `sys_role` (
  `ID` int(11) NOT NULL AUTO_INCREMENT COMMENT '編號',
  `ROLE_NAME` varchar(30) DEFAULT NULL COMMENT '角色名稱',
  `ROLE_DESC` varchar(60) DEFAULT NULL COMMENT '角色描述',
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8;

CREATE TABLE `sys_role_permission` (
  `RID` int(11) NOT NULL COMMENT '角色編號',
  `PID` int(11) NOT NULL COMMENT '權限編號',
  PRIMARY KEY (`RID`,`PID`),
  KEY `FK_Reference_12` (`PID`),
  CONSTRAINT `FK_Reference_11` FOREIGN KEY (`RID`) REFERENCES `sys_role` (`ID`),
  CONSTRAINT `FK_Reference_12` FOREIGN KEY (`PID`) REFERENCES `sys_permission` (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `sys_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(32) NOT NULL COMMENT '用戶名稱',
  `password` varchar(120) NOT NULL COMMENT '密碼',
  `status` int(1) DEFAULT '1' COMMENT '1開啟0關閉',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

CREATE TABLE `sys_user_role` (
  `UID` int(11) NOT NULL COMMENT '用戶編號',
  `RID` int(11) NOT NULL COMMENT '角色編號',
  PRIMARY KEY (`UID`,`RID`),
  KEY `FK_Reference_10` (`RID`),
  CONSTRAINT `FK_Reference_10` FOREIGN KEY (`RID`) REFERENCES `sys_role` (`ID`),
  CONSTRAINT `FK_Reference_9` FOREIGN KEY (`UID`) REFERENCES `sys_user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


3. 創建角色 pojo對象

這里直接使用SpringSecurity的角色規范

package com.example.springboot_security_jsp.domain;

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

/**
 * @author john
 * @date 2020/1/11 - 20:12
 */
public class SysRole implements GrantedAuthority {
    private Integer id;
    private String roleName;
    private String roleDesc;

    public Integer getId() {
        return id;
    }

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

    public String getRoleName() {
        return roleName;
    }

    public void setRoleName(String roleName) {
        this.roleName = roleName;
    }

    public String getRoleDesc() {
        return roleDesc;
    }

    public void setRoleDesc(String roleDesc) {
        this.roleDesc = roleDesc;
    }

    //標記此屬性不做json處理
    @JsonIgnore
    @Override
    public String getAuthority() {
        return roleName;
    }
}

4. 創建用戶pojo

package com.example.springboot_security_jsp.domain;

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

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

/**
 * @author john
 * @date 2020/1/11 - 20:15
 */
public class SysUser implements UserDetails {
    private Integer id;
    private String username;
    private String password;
    private Integer status;
    private List<SysRole> roles = new ArrayList<>();

    public Integer getId() {
        return id;
    }

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

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

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

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }

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

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

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

    @Override
    public String getPassword() {
        return password;
    }

    @Override
    public String getUsername() {
        return username;
    }

    @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;
    }
}

5. 配置application.yml

server:
  port: 8082
spring:
  mvc:
    view:
      suffix: .jsp
      prefix: /pages/
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql:///test
    username: root
    password: root
mybatis:
  type-aliases-package: com.example.springboot_security_jsp.domain
  configuration:
    map-underscore-to-camel-case: true
logging:
  level:
    com.demo: debug

6. 編寫RoleMapper

package com.example.springboot_security_jsp.mapper;

import com.example.springboot_security_jsp.domain.SysRole;
import org.apache.ibatis.annotations.Select;
import tk.mybatis.mapper.common.Mapper;

import java.util.List;

/**
 * @author john
 * @date 2020/1/11 - 20:20
 */
public interface RoleMapper extends Mapper<SysRole> {
    @Select("select r.id,r.role_name roleName ,r.role_desc roleDesc " +
            "FROM sys_role r,sys_user_role ur " +
            "WHERE r.id=ur.rid AND ur.uid=#{uid}")
    public List<SysRole> findByUid(Integer uid);
}

7. 編寫UserMapper

package com.example.springboot_security_jsp.mapper;

import com.example.springboot_security_jsp.domain.SysUser;
import org.apache.ibatis.annotations.Many;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import tk.mybatis.mapper.common.Mapper;

import java.util.List;

/**
 * @author john
 * @date 2020/1/11 - 20:25
 */
public interface UserMapper extends Mapper<SysUser> {
    @Select("select * from sys_user where username=#{username}")
    @Results({
            @Result(id = true, property = "id", column = "id"),
            @Result(property = "roles", column = "id", javaType = List.class,
                    many = @Many(select = "com.example.springboot_security_jsp.mapper.RoleMapper.findByUid"))
    })
    public SysUser findByUsername(String username);
}

8. 編寫UserService以及其實現類

package com.example.springboot_security_jsp.service;

import org.springframework.security.core.userdetails.UserDetailsService;

/**
 * @author john
 * @date 2020/1/11 - 20:31
 */
public interface UserService extends UserDetailsService {

}


package com.example.springboot_security_jsp.service.impl;

import com.example.springboot_security_jsp.mapper.UserMapper;
import com.example.springboot_security_jsp.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author john
 * @date 2020/1/11 - 20:32
 */
@Service
@Transactional
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        return userMapper.findByUsername(username);
    }
}

9. SpringSecurity配置類

package com.example.springboot_security_jsp.config;

import com.example.springboot_security_jsp.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
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.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

/**
 * @author john
 * @date 2020/1/11 - 19:17
 */
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserService userService;
    @Autowired
    private BCryptPasswordEncoder passwordEncoder;

    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    // 認證用戶的來源(內存或者數據庫)
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService).passwordEncoder(passwordEncoder);
    }

    //配置springsecurity相關信息
    protected void configure(HttpSecurity http) throws Exception {
        // 釋放靜態資源,指定資源攔截規則,指定自定義認證頁面,指定退出認證配置,csrf配置
        http.authorizeRequests()
                .antMatchers("/login.jsp", "/failer.jsp", "/css/**", "/img/**", "/plugins/**")
                .permitAll()
                .antMatchers("/**").hasAnyRole("USER", "ADMIN")
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/login.jsp")
                .loginProcessingUrl("/login")
                .successForwardUrl("/index.jsp")
                .failureForwardUrl("/failer.jsp")
                .permitAll()
                .and()
                .logout()
                .logoutUrl("/logout")
                .logoutSuccessUrl("/login.jsp")
                .invalidateHttpSession(true)
                .permitAll();
        //禁用csrf
//                .and()
//                .csrf()
//                .disable();
    }

}

10. 編寫啟動類

package com.example.springboot_security_jsp;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import tk.mybatis.spring.annotation.MapperScan;

@SpringBootApplication
@MapperScan("com.example.springboot_security_jsp.mapper")
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SpringbootSecurityJspApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootSecurityJspApplication.class, args);
    }

}

11. 編寫一個控制器用於訪問

package com.example.springboot_security_jsp.controller;

import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * @author john
 * @date 2020/1/11 - 19:07
 */
@Controller
@RequestMapping("/product")
public class ProductController {
    @RequestMapping("/findAll")
    @Secured("ROLE_PRODUCT")
    public String hello() {
        return "product-list";
    }
}

12. 配置異常攔截器

package com.example.springboot_security_jsp.controller.advice;

import org.springframework.security.access.AccessDeniedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

/**
 * @author john
 * @date 2020/1/11 - 20:40
 */
@ControllerAdvice
public class HandleControllerException {
    @ExceptionHandler(RuntimeException.class)
    public String exceptionHandler(RuntimeException e) {
        if (e instanceof AccessDeniedException) {
            //如果是權限不足異常,則跳轉到權限不足頁面!
            return "redirect:/403.jsp";
        }
        //其余的異常都到500頁面!
        return "redirect:/500.jsp";
    }
}

13. 測試

jsp等靜態頁面資源查看碼雲代碼

SpringBoot官方是不推薦在SpringBoot中使用jsp的,需要導入tomcat插件啟動項目,不能再用SpringBoot默認tomcat了

在maven中執行

mvn spring-boot:run

打開瀏覽器訪問<http://localhost:8082/login.jsp>

輸入用戶名john密碼123

登錄成功

當訪問權限不足的頁面會顯示自定義頁面

正常訪問其他頁面

14. 代碼地址

demo項目

15. 知識點備忘

1. Spring Security主要jar包功能介紹

Spring Security主要jar包功能介紹
spring-security-core.jar
核心包,任何Spring Security功能都需要此包。
spring-security-web.jar
web工程必備,包含過濾器和相關的Web安全基礎結構代碼。
spring-security-config.jar
用於解析xml配置文件,用到Spring Security的xml配置文件的就要用到此包。
spring-security-taglibs.jar
Spring Security提供的動態標簽庫,jsp頁面可以用

2. Spring Security 常用過濾器介紹

1. org.springframework.security.web.context.SecurityContextPersistenceFilter

首當其沖的一個過濾器,作用之重要,自不必多言。
SecurityContextPersistenceFilter主要是使用SecurityContextRepositorysession中保存或更新一個SecurityContext,並將SecurityContext給以后的過濾器使用,來為后續filter建立所需的上下文。
SecurityContext中存儲了當前用戶的認證以及權限信息。
2. org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter
此過濾器用於集成SecurityContextSpring異步執行機制中的WebAsyncManager
3 . org.springframework.security.web.header.HeaderWriterFilter
向請求的Header中添加相應的信息,可在http標簽內部使用security:headers來控制
4 . org.springframework.security.web.csrf.CsrfFilter
csrf又稱跨域請求偽造,SpringSecurity會對所有post請求驗證是否包含系統生成的csrftoken信息,
如果不包含,則報錯。起到防止csrf攻擊的效果。
5. org.springframework.security.web.authentication.logout.LogoutFilter
匹配 URL/logout的請求,實現用戶退出,清除認證信息。
6 . org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
認證操作全靠這個過濾器,默認匹配URL/login且必須為POST請求。
7 . org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter
如果沒有在配置文件中指定認證頁面,則由該過濾器生成一個默認認證頁面。
8 . org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter
由此過濾器可以生產一個默認的退出登錄頁面
9 . org.springframework.security.web.authentication.www.BasicAuthenticationFilter
此過濾器會自動解析HTTP請求中頭部名字為Authentication,且以Basic開頭的頭信息。
10 . org.springframework.security.web.savedrequest.RequestCacheAwareFilter
通過HttpSessionRequestCache內部維護了一個RequestCache,用於緩存HttpServletRequest
11 . org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter
針對ServletRequest進行了一次包裝,使得request具有更加豐富的API
12 . org.springframework.security.web.authentication.AnonymousAuthenticationFilter
SecurityContextHolder中認證信息為空,則會創建一個匿名用戶存入到SecurityContextHolder中。
spring security為了兼容未登錄的訪問,也走了一套認證流程,只不過是一個匿名的身份。
13 . org.springframework.security.web.session.SessionManagementFilter
SecurityContextRepository限制同一用戶開啟多個會話的數量
14 . org.springframework.security.web.access.ExceptionTranslationFilter
異常轉換過濾器位於整個springSecurityFilterChain的后方,用來轉換整個鏈路中出現的異常
15 . org.springframework.security.web.access.intercept.FilterSecurityInterceptor
獲取所配置資源訪問的授權信息,根據SecurityContextHolder中存儲的用戶信息來決定其是否有權限。

3. csrf處理

1. 禁用csrf,在配置文件編寫(不推薦)

2. 在認證頁面攜帶token請求

4. 退出登錄

注意:一旦開啟了csrf防護功能,logout處理器便只支持POST請求方式了!

<form action="${pageContext.request.contextPath}/logout" method="post">
<security:csrfInput/>
<input type="submit" value="注銷">
</form>

5. remember me頁面

<!-- 注意name和value屬性的值不要寫錯哦 -->
<input type="checkbox" name="remember-me" value="true"> 

6. 持久化remember me信息

創建一張表,注意這張表的名稱和字段都是固定的,不要修改。

CREATE TABLE `persistent_logins` (
`username` varchar(64) NOT NULL,
`series` varchar(64) NOT NULL,
`token` varchar(64) NOT NULL,
`last_used` timestamp NOT NULL,
PRIMARY KEY (`series`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

在代碼中如下配置

	@Autowired
    private DataSource dataSource;

	// 1. 配置TokenRepository
    @Bean
    public PersistentTokenRepository persistentTokenRepository() {
        JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
        tokenRepository.setDataSource(dataSource);
        //自動創建上面的表
        tokenRepository.setCreateTableOnStartup(true);
        return tokenRepository;
    }

	@Override
    protected void configure(HttpSecurity http) throws Exception {
        // 表單登錄
        http    
                //記住我的配置
                // rememberMe需要的配置包含TokenRepository對象以及token過期時間
                .rememberMe()
                .tokenRepository(persistentTokenRepository())
                .tokenValiditySeconds(60 * 60 * 24)
                .userDetailsService(userDetailsService);
    }

7. 在頁面中顯示當前認證用戶名

<span class="hidden-xs">
<security:authentication property="principal.username" />
</span>
或者
<span class="hidden-xs">
<security:authentication property="name" />
</span>

8. 在頁面中控制連接是否顯示

 					<%-- 管理員和商品管理權限可以--%>
                    <security:authorize access="hasAnyRole('ROLE_PRODUCT','ROLE_ADMIN')">
                        <li id="system-setting"><a
                                href="${pageContext.request.contextPath}/product/findAll">
                            <i class="fa fa-circle-o"></i> 產品管理
                        </a></li>
                    </security:authorize>
                    <%-- 管理員和訂單權限可以--%>
                    <security:authorize access="hasAnyRole('ROLE_ORDER','ROLE_ADMIN')">
                        <li id="system-setting"><a
                                href="${pageContext.request.contextPath}/order/findAll">
                            <i class="fa fa-circle-o"></i> 訂單管理
                        </a></li>
                    </security:authorize>

9. 授權操作

SpringSecurity可以通過注解的方式來控制類或者方法的訪問權限。

1. securedEnabled

securedEnabledSpringSecurity提供的注解

在入口處配置

@SpringBootApplication
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SpringbootSecurityJspApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootSecurityJspApplication.class, args);
    }

}

controller處寫

@Controller
@RequestMapping("/product")
public class ProductController {
    @Secured({"ROLE_PRODUCT","ROLE_ADMIN"})  //springsecurity內部的權限控制注解開關
    @RequestMapping("/findAll")
    public String findAll(){
        return "product-list";
    }
}
2. jsr250注解

在入口處配置

@SpringBootApplication
//表示支持jsr250-api的注解,需要jsr250-api的jar包
@EnableGlobalMethodSecurity(jsr250Enabled = true)
public class SpringbootSecurityJspApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootSecurityJspApplication.class, args);
    }

}

controller處寫

@Controller
@RequestMapping("/product")
public class ProductController {
   
    @RolesAllowed({"ROLE_PRODUCT", "ROLE_ADMIN"}) //jsr250注解
    @RequestMapping("/findAll")
    public String findAll() {
        return "product-list";
    }
}

3. prePostEnabled

在入口處配置

@SpringBootApplication
//表示支持spring表達式注解
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SpringbootSecurityJspApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootSecurityJspApplication.class, args);
    }

}

controller處寫(如下兩種方式)

@Controller
@RequestMapping("/product")
public class ProductController {
    //SpringSecurity提供的注解
//    @PreAuthorize("hasAnyRole('ROLE_PRODUCT','ROLE_ADMIN')")
    @PreAuthorize("hasAnyAuthority('ROLE_PRODUCT','ROLE_ADMIN')")
    @RequestMapping("/findAll")
    public String findAll(){
        return "product-list";
    }
}

以上三種選一種即可

10. 編寫異常處理器處理異常

@ControllerAdvice
public class ControllerExceptionAdvice {
    //只有出現AccessDeniedException異常才調轉403.jsp頁面
    @ExceptionHandler(AccessDeniedException.class)
    public String exceptionAdvice(){
    	return "forward:/403.jsp";
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM