05.SSM整合案例的基本介紹html
06.產品操做前端
07.訂單操做java
08.權限控制web
09.用戶操做spring
10.權限關聯與控制sql
11.AOP日誌數據庫
SSM權限操做express
若是刪除TABLE ,須要先刪除多對多建立的中間表後,才能刪除其它主鍵關聯的表。apache
本案例使用oracle數據庫
-- 1.1.2 sql語句 CREATE TABLE users( id varchar2(32) default SYS_GUID() PRIMARY KEY, email VARCHAR2(50) UNIQUE NOT NULL, username VARCHAR2(50), PASSWORD VARCHAR2(50), phoneNum VARCHAR2(20), STATUS INT )
實體類
package cn.bjut.ssm.domain; import java.util.List; public class UserInfo { private String id; private String username; private String email; private String password; private String phoneNum; private Integer status; //======成員變量是其它實體類的List<E>===== private String statusStr; private List<Role> roles; public String getStatusStr() { //狀態0 未開啓 1 開啓 if(status!=null){ if(status==0) statusStr="未開啓"; if(status==1) statusStr="開啓"; } return statusStr; } public void setStatusStr(String statusStr) { this.statusStr = statusStr; } //==========其它get/set方法===============
1.2 角色表
-- 1.2.2 sql語句 CREATE TABLE role( id varchar2(32) default SYS_GUID() PRIMARY KEY, roleName VARCHAR2(50) , roleDesc VARCHAR2(50) )
package cn.bjut.ssm.domain; import org.springframework.security.core.userdetails.User; import java.util.List; public class Role { private String id; private String roleName; private String roleDesc; private List<Permission> permissions; private List<User> users; //=====Role與User以及Permission都是多對多的關係
1.2.3 用戶與角色關聯關係
用戶與角色之間是多對多關係,咱們經過user_role表來描述其關聯,在實體類中User中存在List,在Role中有List
-- 用戶與角色關聯表 CREATE TABLE users_role( userId varchar2(32), roleId varchar2(32), PRIMARY KEY(userId,roleId), FOREIGN KEY (userId) REFERENCES users(id), FOREIGN KEY (roleId) REFERENCES role(id) )
1.3 資源權限表
-- 1.3.2 sql語句 CREATE TABLE permission( id varchar2(32) default SYS_GUID() PRIMARY KEY, permissionName VARCHAR2(50) , url VARCHAR2(50) )
package cn.bjut.ssm.domain; import java.util.List; public class Permission { private String id; private String permissionName; private String url; private List<Role> roles; //=====存在一對多關係,則在一的實體類中的成員變量類型是多的List<E> //=====存在一對多關係,則在一的實體類中的成員變量名稱是多的names
1.3.3.權限資源與角色關聯關係
權限資源與角色是多對多關係,咱們使用role_permission表來描述。在實體類Permission中存在List,在Role類中有List
-- 權限資源與角色是多對多關係 CREATE TABLE role_permission( permissionId varchar2(32), roleId varchar2(32), PRIMARY KEY(permissionId,roleId), FOREIGN KEY (permissionId) REFERENCES permission(id), FOREIGN KEY (roleId) REFERENCES role(id) )
Spring Security 是 Spring 項目組中用來提供安全服務的框架。 安全包括兩個主要操做:
「認證」
「受權」
maven依賴
<dependencies> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-web</artifactId> <version>5.0.10.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> <version>5.0.10.RELEASE</version> </dependency> </dependencies>
一、導入maven依賴座標
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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>cn.bjut</groupId> <artifactId>springSecurityTest</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <name>springSecurityTest Maven Webapp</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <properties> <spring.version>5.0.15.RELEASE</spring.version> <spring.security.version>5.0.10.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> <finalName>springSecurityTest</finalName> <plugins> <!-- java編譯插件 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</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> <version>2.2</version> <configuration> <!-- 指定端口 --> <port>8090</port> <!-- 請求路徑 --> <path>/</path> </configuration> </plugin> </plugins> </build> </project>
二、在WEB-INF目錄下的 web.xml中配置<filter>
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <display-name>SpringSecurityTest</display-name> <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> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> </web-app>
三、在 classpath: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 auto-config="true" use-expressions="false"> <!-- intercept-url定義一個過濾規則 pattern表示對哪些url進行權限控制,access屬性表示在請求對應 的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>
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" authentication-success-forward-url="/success.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>
在Spring Security中若是想要使用數據進行認證操做,有不少種操做方式,這裏咱們介紹使用UserDetails接口、UserDetailsService來完成操做。
UserDetails做用是於封裝當前進行認證的用戶信息,但因爲其是一個接口,
因此咱們能夠對其進行實現,也能夠使用Spring Security提供的一個UserDetails的實現類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; }
3.1 用戶登陸
webapp/WEB-INF目錄下的
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <!-- 聲明加載spring框架配置文件的路徑 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath*:applicationContext.xml,classpath*:spring-security.xml</param-value> </context-param> <!-- 配置spring-web監聽器 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 配置監聽器,監聽request域對象的建立和銷燬的 --> <listener> <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> </listener> <!-- 前端控制器(加載classpath:springmvc.xml 服務器啓動建立servlet) --> <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 配置初始化參數,建立完DispatcherServlet對象,加載springmvc.xml配置文件 --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:springmvc.xml</param-value> </init-param> <!-- 服務器啓動的時候,讓DispatcherServlet對象建立 --> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> <!-- 解決中文亂碼過濾器 --> <filter> <filter-name>characterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>characterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!--委派springSecurity過濾器--> <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> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> </web-app>
配置在web項目的resources目錄下的
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 pattern="/login.jsp" security="none"/> <security:http pattern="/failer.jsp" security="none"/> <security:http pattern="/css/**" security="none"/> <security:http pattern="/img/**" security="none"/> <security:http pattern="/images/**" security="none"/> <security:http pattern="/plugins/**" security="none"/> <!-- 配置具體的規則 auto-config="false" 選用本身編寫登陸的頁面,不用框架提供的默認登陸頁面 use-expressions="false" 是否使用SPEL表達式(還沒學習過) --> <security:http auto-config="false" use-expressions="true" > <!-- 配置具體的攔截的規則 pattern="請求路徑的規則" access="訪問系統的人,必須有ROLE_USER的角色" --> <security:intercept-url pattern="/**" access="hasAnyRole('ROLE_USER','ROLE_ADMIN')"/> <!--<security:intercept-url pattern="/**" access="ROLE_USER,ROLE_ADMIN"/>--> <!--若是沒有login-processing-url這一屬性,那麼登陸表單的action,必須爲j_spring_secutity_check--> <!-- 定義跳轉的具體的頁面 --> <security:form-login login-page="/login.jsp" login-processing-url="/login" username-parameter="username" password-parameter="password" default-target-url="/index.jsp" authentication-failure-url="/failer.jsp" authentication-success-forward-url="/index.jsp" /> <!-- 關閉跨域請求 --> <security:csrf disabled="true"/> <!-- 退出 --> <security:logout invalidate-session="true" logout-url="/logout.do" logout-success-url="/login.jsp" /> </security:http> <!-- 切換成數據庫中的用戶名和密碼 --> <security:authentication-manager> <security:authentication-provider user-service-ref="userService"> <!-- 配置加密的方式 --> <!--<security:password-encoder ref="passwordEncoder"/>--> </security:authentication-provider> </security:authentication-manager> <!-- 配置加密類 --> <!--<bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>--> <!-- 提供了入門的方式,在內存中存入用戶名和密碼 <security:authentication-manager> <security:authentication-provider> <security:user-service> <security:user name="admin" password="{noop}admin" authorities="ROLE_USER"/> </security:user-service> </security:authentication-provider> </security:authentication-manager> --> </beans>
本身編寫用到的
userServiceImpl實現類
package cn.bjut.ssm.service.impl; import cn.bjut.ssm.dao.IUserDao; import cn.bjut.ssm.domain.UserInfo; import cn.bjut.ssm.service.IUserService; import org.springframework.beans.factory.annotation.Autowired; 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.UsernameNotFoundException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.List; @Service(value = "userService") @Transactional //註解的方式使用spring事務管理 public class UserServiceImpl implements IUserService { @Autowired IUserDao userDao; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { //UserInfo是domain包下的實體類 UserInfo userInfo = null; try{ userInfo = userDao.findByUsername(username); } catch(Exception e){ e.printStackTrace(); } //把本身查詢到的實體類中的認證信息封裝成UserDetails //"{noop}"使用密碼明文的必要前綴 User user = new User(userInfo.getUsername(),"{noop}"+userInfo.getPassword(),getAuthority()); return user; } //這個成員方法做用就是返回一個List集合,集合中裝入的是角色描述。 //實際項目中應該是從數據庫中獲取role描述後封裝到這個方法體裏面。 public List<SimpleGrantedAuthority> getAuthority(){ List<SimpleGrantedAuthority> list = new ArrayList<>(); // new 匿名對象 list.add(new SimpleGrantedAuthority("ROLE_USER")); return list; } }
在DAO層寫一個Java的 Interface ,用來查詢用戶信息,獲取username和password查詢結果集封裝在實體類中。
package cn.bjut.ssm.dao; import cn.bjut.ssm.domain.UserInfo; import org.apache.ibatis.annotations.Select; public interface IUserDao { @Select("select * from USERS where username = #{username}") public UserInfo findByUsername(String username) throws Exception; }
使用PL/SQL Developer插入一條完整用戶數據到USERS表以下:
-- 查詢user表 select * from users t; -- 插入一條users表數據 insert into users values('1101112019','itheima@itcast.cn','ssm08','itheima','15612345678',1);
運行版本報錯信息爲:WARN o.bcrypt.BCryptPasswordEncoder - Encoded password does not look like BCrypt;
由於spring-security在最新版本升級後,默認把以前的明文密碼方式給去掉了官方文檔說明。
參考資料:
使用Spring Security下的BCryptPasswordEncoder進行密碼加密
SpringBoot Security:Encoded password does not look like BCrypt 解決
spring-cloud-oauth2升級版本遇到的認證報bad credentials,Encoded password does not look likebcrypt的問題
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <html> <head> <title>默認主頁</title> </head> <body> <p>你正在瀏覽webapp目錄下的index.jsp</p><br> 超連接標籤請求的href後面訪問不到WEB-INF目錄裏的jsp文件<br> <a href="${pageContext.request.contextPath}/pages/main.jsp">點擊跳轉到:/webapp/pages/main.jsp</a><br> <%--<jsp:forward page="/pages/main.jsp"></jsp:forward>--%> <jsp:forward page="./WEB-INF/pages2/main2.jsp"></jsp:forward> </body> </html>
截止目前我發現若是瀏覽器想訪問WEB-INF目錄裏的.jsp頁面,首先能夠經過springMVC的視圖解析器配置經過返回ModelAndView訪問到,再有就是經過<jsp:forward page=" /WEB-INF"> 跳轉訪問。
-- 插入一條記錄到角色表記錄 insert into ROLE values ('12345','ADMIN','vip'); -- 插入一條用戶-角色中間表記錄 insert into USERS_ROLE values('1101112019','12345');
package cn.bjut.ssm.dao; import cn.bjut.ssm.domain.Role; import org.apache.ibatis.annotations.Select; import java.util.List; public interface IRoleDao { //根據用戶ID查詢出全部對應的角色 @Select("select * from ROLE where id in( select ROLEID from USERS_ROLE where USERID = #{userId})") public List<Role> findRoleByUserId(String userId) throws Exception; }
public interface IUserDao { @Select("select * from USERS where username = #{username}") @Results({ @Result(property = "id",column = "id",id = true), @Result(property = "username",column = "username"), @Result(property = "email",column = "email"), @Result(property = "password",column = "password"), @Result(property = "phoneNum",column = "phoneNum"), @Result(property = "status",column = "status"), //經過中間表查詢多對多關係,返回一個其它實體類的List集合 @Result(property = "roles",column = "id",javaType =java.util.List.class,many = @Many(select = "cn.bjut.ssm.dao.IRoleDao.findRoleByUserId")) }) public UserInfo findByUsername(String username) throws Exception; }
這是不考慮Role的可用/不可用狀態時的認證明現類
@Service(value = "userService") @Transactional //註解的方式使用spring事務管理 public class UserServiceImpl implements IUserService { @Autowired IUserDao userDao; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { //UserInfo是domain包下的實體類 UserInfo userInfo = null; try{ userInfo = userDao.findByUsername(username); } catch(Exception e){ e.printStackTrace(); } //把本身查詢到的實體類中的認證信息封裝成UserDetails //"{noop}"使用密碼明文的必要前綴 User user = new User(userInfo.getUsername(),"{noop}"+userInfo.getPassword(),getAuthority(userInfo.getRoles())); return user; } //這個成員方法做用就是返回一個List集合,集合中裝入的是角色描述。 //實際項目中應該是從數據庫中獲取role描述後封裝到這個方法體裏面。 public List<SimpleGrantedAuthority> getAuthority(List<Role> roles){ List<SimpleGrantedAuthority> list = new ArrayList<>(); //加強for循環 for (Role role :roles){ // new 匿名對象 list.add(new SimpleGrantedAuthority("ROLE_"+role.getRoleName())); } return list; }
考慮用戶表中狀態值:
//狀態0 未開啓 1 開啓
使用了三元運算符進行判斷
@Service(value = "userService") @Transactional //註解的方式使用spring事務管理 public class UserServiceImpl implements IUserService { @Autowired IUserDao userDao; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { //UserInfo是domain包下的實體類 UserInfo userInfo = null; try{ userInfo = userDao.findByUsername(username); } catch(Exception e){ e.printStackTrace(); } //把本身查詢到的實體類中的認證信息封裝成UserDetails //"{noop}"使用密碼明文的必要前綴 // User user = new User(userInfo.getUsername(),"{noop}"+userInfo.getPassword(),getAuthority(userInfo.getRoles())); User user = new User(userInfo.getUsername(),"{noop}"+userInfo.getPassword(),userInfo.getStatus() ==0 ?false:true,true,true,true,getAuthority(userInfo.getRoles())); return user; } //這個成員方法做用就是返回一個List集合,集合中裝入的是角色描述。 //實際項目中應該是從數據庫中獲取role描述後封裝到這個方法體裏面。 public List<SimpleGrantedAuthority> getAuthority(List<Role> roles){ List<SimpleGrantedAuthority> list = new ArrayList<>(); //加強for循環 for (Role role :roles){ // new 匿名對象 list.add(new SimpleGrantedAuthority("ROLE_"+role.getRoleName())); } return list; }
====================
end