1、簡介css
Web應用的安全管理,主要包括兩個方面的內容:身份認證、用戶受權,此處使用spring-cloud-security來講明。html
2、依賴管理java
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-security</artifactId> </dependency> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-springsecurity4</artifactId> </dependency>
3、安全策略配置web
Spring Security已經大致實現了,咱們這裏只是須要一些配置與引用。
spring
package com.example.demo.config; import com.example.demo.utils.security.CustomUserService; import com.example.demo.utils.security.LoginSuccessHandler; import com.example.demo.utils.security.MyFilterSecurityInterceptor; import com.example.demo.utils.security.SecuritySettings; import org.apache.commons.lang3.StringUtils; 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.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.web.access.intercept.FilterSecurityInterceptor; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; /** * Security安全配置 * * @Author: 我愛大金子 * @Description: Security安全配置 * @Date: Create in 15:20 2017/7/5 */ @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private CustomFilterSecurityInterceptor customFilterSecurityInterceptor; // 權限管理過濾器 @Autowired private SecuritySettings securitySettings; // 自定義安全配置類 /**註冊UserDetailsService的bean*/ @Bean public UserDetailsService customUserService(){ return new CustomUserService(); } /**登陸認證*/ @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(customUserService()); //userDetailsService驗證 } /***設置不攔截規則*/ @Override public void configure(WebSecurity web) throws Exception { web.ignoring().antMatchers("/js/**", "/css/**", "/images/**", "/druid/**"); } /**安全策略配置*/ @Override protected void configure(HttpSecurity http) throws Exception { // 設置遊客能夠訪問的URI if (StringUtils.isNotBlank(securitySettings.getPermitall())) { http.authorizeRequests().antMatchers(securitySettings.getPermitall().split(",")).permitAll(); } http.authorizeRequests() .anyRequest().authenticated() //任何請求,登陸後能夠訪問 // 配置登陸URI、登陸失敗跳轉URI與登陸成功後默認跳轉URI .and().formLogin().loginPage("/login").failureUrl("/login?error").permitAll().defaultSuccessUrl("/", true).successHandler(loginSuccessHandler()) // 註銷行爲任意訪問 .and().logout().permitAll() // 設置拒絕訪問的提示URI .and().exceptionHandling().accessDeniedPage("/login?illegal") ; http.addFilterBefore(myFilterSecurityInterceptor, FilterSecurityInterceptor.class); } /**登陸成功處理器*/ private AuthenticationSuccessHandler loginSuccessHandler() { return new LoginSuccessHandler(); } }
說明:apache
loginPage:設置一個實驗自定義的登陸URIbootstrap
loginSuccessHandler:設置自定義的登陸處理器安全
permitAll:是容許訪問mybatis
accessDeniedPage:配置拒絕訪問的提示URIapp
antMatchers:對URI的配置
假設我要管理員才能夠訪問admin文件夾下的內容,如:.antMatchers("/admin/**").hasRole("ROLE_ADMIN"),
也能夠設置admin文件夾下的文件能夠有多個角色來訪問,如:.antMatchers("/admin/**").hasAnyRole("ROLE_ADMIN","ROLE_USER")
也能夠經過hasIpAddress來指定某一個ip能夠訪問該資源,寫法以下.antMatchers("/admin/**").hasIpAddress("210.210.210.210")
3.一、自定義安全配置類
爲是更方便的使用springSecurity,咱們自定義一個權限的配置類,如配置登陸的URI、遊客訪問的URI等配置項
package com.example.demo.utils.security; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; /** * 自定義安全配置類 * * @Author: 我愛大金子 * @Description: 自定義安全配置類 * @Date: Create in 9:45 2017/7/6 */ @Configuration @ConfigurationProperties(prefix = "securityConfig") public class SecuritySettings { /**容許訪問的URL,多個用逗號分隔*/ private String permitall; public String getPermitall() { return permitall; } public void setPermitall(String permitall) { this.permitall = permitall; } }
3.二、登陸成功處理器
登陸成功後,若是須要對用戶的行爲作一些記錄或者執行其它操做,則可使用登陸成功處理器。
package com.example.demo.utils.security; import com.example.demo.pojo.SysUser; import org.springframework.security.core.Authentication; import org.springframework.security.core.userdetails.User; import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * 登陸成功處理器 * * @Author: 我愛大金子 * @Description: 登陸成功處理器 * @Date: Create in 11:35 2017/7/6 */ public class LoginSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler { @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws ServletException, IOException { User userDetails = (User) authentication.getPrincipal(); System.out.println("登陸用戶:username=" + userDetails.getUsername() + ", uri=" + request.getContextPath()); super.onAuthenticationSuccess(request, response, authentication); } }
3.三、springMVC 配置(訪問 /login 轉向 login.html 頁面)
package com.example.demo.config; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; /** * springMVC 配置(註冊訪問 /login 轉向 login.html 頁面) * * @Author: 我愛大金子 * @Description: springMVC 配置(註冊訪問 /login 轉向 login.html 頁面) * @Date: Create in 16:24 2017/7/5 */ @Configuration public class WebMvcConfig extends WebMvcConfigurerAdapter { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/login").setViewName("login"); } }
4、登陸認證
在安全策略配置代碼中有,主要看自定義的CustomUserService,此類實現了UserDetailsService接口,重寫了loadUserByUsername方法
package com.example.demo.utils.security; import com.example.demo.dao.SysPermissionDao; import com.example.demo.dao.SysUserDao; import com.example.demo.pojo.SysPermission; import org.springframework.security.core.userdetails.User; import com.example.demo.pojo.SysUser; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import java.util.ArrayList; import java.util.List; /** * 自定義UserDetailsService,將用戶權限交給springsecurity進行管控 * * @Author: 我愛大金子 * @Description: 將用戶權限交給Springsecurity進行管控 * @Date: Create in 16:19 2017/7/5 */ public class CustomUserService implements UserDetailsService { @Autowired private SysUserDao sysUserDao; @Autowired private SysPermissionDao sysPermissionDao; @Override public UserDetails loadUserByUsername(String username) { SysUser user = sysUserDao.findByUserName(username); if (user != null) { List<SysPermission> permissions = sysPermissionDao.findByAdminUserId(user.getId()); List<GrantedAuthority> grantedAuthorities = new ArrayList <>(); for (SysPermission permission : permissions) { if (permission != null && permission.getName()!=null) { GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(permission.getName()); //1:此處將權限信息添加到 GrantedAuthority 對象中,在後面進行全權限驗證時會使用GrantedAuthority 對象。 grantedAuthorities.add(grantedAuthority); } } return new User(user.getUsername(), user.getPassword(), grantedAuthorities); } else { throw new UsernameNotFoundException("admin: " + username + " do not exist!"); } } }
5、權限管理
在Security安全配置類中使用了權限管理過濾器CustomFilterSecurityInterceptor
package com.example.demo.utils.security; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.SecurityMetadataSource; import org.springframework.security.access.intercept.AbstractSecurityInterceptor; import org.springframework.security.access.intercept.InterceptorStatusToken; import org.springframework.security.web.FilterInvocation; import org.springframework.stereotype.Service; import java.io.IOException; /** * 權限管理過濾器 * * @Author: 我愛大金子 * @Description: 權限管理過濾器 * @Date: Create in 17:16 2017/7/5 */ @Service public class CustomFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter { @Autowired private CustomFilterInvocationSecurityMetadataSource customFilterInvocationSecurityMetadataSource; // 權限配置資源管理器 /**權限管理決斷器*/ @Autowired public void setMyAccessDecisionManager(CustomAccessDecisionManager customAccessDecisionManager) { super.setAccessDecisionManager(customAccessDecisionManager); } @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { FilterInvocation fi = new FilterInvocation(request, response, chain); invoke(fi); } public void invoke(FilterInvocation fi) throws IOException, ServletException { //fi裏面有一個被攔截的url //裏面調用MyInvocationSecurityMetadataSource的getAttributes(Object object)這個方法獲取fi對應的全部權限 //再調用MyAccessDecisionManager的decide方法來校驗用戶的權限是否足夠 InterceptorStatusToken token = super.beforeInvocation(fi); try { //執行下一個攔截器 fi.getChain().doFilter(fi.getRequest(), fi.getResponse()); } finally { super.afterInvocation(token, null); } } @Override public void destroy() { } @Override public Class<?> getSecureObjectClass() { return FilterInvocation.class; } @Override public SecurityMetadataSource obtainSecurityMetadataSource() { return this.customFilterInvocationSecurityMetadataSource; } }
說明:
customFilterSecurityInterceptor:權限管理過濾器
customAccessDecisionManager:權限管理決斷器
customFilterInvocationSecurityMetadataSource:權限配置資源管理器
其中過濾器在系統啓動時開始工做,並同時導入權限配置資源管理器和權限管理決斷器,對用戶訪問的資源進行管理。權限管理決斷器對用戶訪問的資源與用戶擁有的角色權限進行對比,以此來判斷用戶是否對某個資源具備訪問權限。
5.一、權限管理過濾器
繼承與AbstractSecurityInterceptor,實時監控用戶的行爲,防止用戶訪問未被受權的資源。
package com.example.demo.utils.security; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.SecurityMetadataSource; import org.springframework.security.access.intercept.AbstractSecurityInterceptor; import org.springframework.security.access.intercept.InterceptorStatusToken; import org.springframework.security.web.FilterInvocation; import org.springframework.stereotype.Service; import java.io.IOException; /** * 權限管理過濾器 * * @Author: 我愛大金子 * @Description: 權限管理過濾器 * @Date: Create in 17:16 2017/7/5 */ @Service public class CustomFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter { Logger log = LoggerFactory.getLogger(CustomFilterSecurityInterceptor.class); @Autowired private CustomFilterInvocationSecurityMetadataSource customFilterInvocationSecurityMetadataSource; // 權限配置資源管理器 /**權限管理決斷器*/ @Autowired public void setMyAccessDecisionManager(CustomAccessDecisionManager customAccessDecisionManager) { super.setAccessDecisionManager(customAccessDecisionManager); } @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { FilterInvocation fi = new FilterInvocation(request, response, chain); log.info("【權限管理過濾器】請求URL:" + fi.getRequestUrl()); invoke(fi); } public void invoke(FilterInvocation fi) throws IOException, ServletException { //fi裏面有一個被攔截的url //裏面調用CustomFilterInvocationSecurityMetadataSource的getAttributes(Object object)這個方法獲取fi對應的全部權限 //再調用CustomAccessDecisionManager的decide方法來校驗用戶的權限是否足夠 InterceptorStatusToken token = super.beforeInvocation(fi); try { //執行下一個攔截器 fi.getChain().doFilter(fi.getRequest(), fi.getResponse()); } catch(Exception e) { log.error("【權限管理過濾器】【異常】" + e.getMessage(), e); } finally { super.afterInvocation(token, null); } } @Override public void destroy() { } @Override public Class<?> getSecureObjectClass() { return FilterInvocation.class; } @Override public SecurityMetadataSource obtainSecurityMetadataSource() { return this.customFilterInvocationSecurityMetadataSource; } }
5.二、權限管理決斷器
權限管理的關鍵部分就是決斷器,它實現了AccessDecisionManager,重寫了decide方法,使用自定義的決斷器,在用戶訪問受保護的資源時,決斷器判斷用戶擁有的角色中是否對改資源具備訪問權限,若是沒有,則拒絕訪問
package com.example.demo.utils.security; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.access.AccessDecisionManager; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.access.ConfigAttribute; import org.springframework.security.authentication.InsufficientAuthenticationException; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.stereotype.Service; import java.util.Collection; import java.util.Iterator; /** * 權限管理決斷器 * * @Author: 我愛大金子 * @Description: 權限管理決斷器 * @Date: Create in 17:15 2017/7/5 */ @Service public class CustomAccessDecisionManager implements AccessDecisionManager { Logger log = LoggerFactory.getLogger(CustomAccessDecisionManager.class); // decide 方法是斷定是否擁有權限的決策方法, //authentication 是釋CustomUserService中循環添加到 GrantedAuthority 對象中的權限信息集合. //object 包含客戶端發起的請求的requset信息,可轉換爲 HttpServletRequest request = ((FilterInvocation) object).getHttpRequest(); //configAttributes 爲MyInvocationSecurityMetadataSource的getAttributes(Object object)這個方法返回的結果,此方法是爲了斷定用戶請求的url 是否在權限表中,若是在權限表中,則返回給 decide 方法,用來斷定用戶是否有此權限。若是不在權限表中則放行。 @Override public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException { if(null== configAttributes || configAttributes.size() <=0) { return; } ConfigAttribute c; String needRole; for(Iterator<ConfigAttribute> iter = configAttributes.iterator(); iter.hasNext(); ) { c = iter.next(); needRole = c.getAttribute(); for(GrantedAuthority ga : authentication.getAuthorities()) {//authentication 爲在註釋1 中循環添加到 GrantedAuthority 對象中的權限信息集合 if(needRole.trim().equals(ga.getAuthority())) { return; } } log.info("【權限管理決斷器】須要role:" + needRole); } throw new AccessDeniedException("Access is denied"); } @Override public boolean supports(ConfigAttribute attribute) { return true; } @Override public boolean supports(Class<?> clazz) { return true; } }
5.三、權限配置資源管理器
權限配置資源管理器實現了FilterInvocationSecurityMetadataSource,在啓動時就去加載了全部的權限列表,權限配置資源管理器爲決斷器實時提供支持,判斷用戶訪問的資源是否在受保護的範圍以內。
package com.example.demo.utils.security; import com.example.demo.dao.SysPermissionDao; import com.example.demo.pojo.SysPermission; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.ConfigAttribute; import org.springframework.security.access.SecurityConfig; import org.springframework.security.web.FilterInvocation; import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest; import java.util.*; /** * 權限配置資源管理器 * * @Author: 我愛大金子 * @Description: 權限配置資源管理器 * @Date: Create in 17:17 2017/7/5 */ @Service public class CustomFilterInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource { @Autowired private SysPermissionDao sysPermissionDao; private HashMap<String, Collection<ConfigAttribute>> map =null; /** * 加載權限表中全部權限 */ public void loadResourceDefine(){ map = new HashMap<>(); Collection<ConfigAttribute> array; ConfigAttribute cfg; List<SysPermission> permissions = sysPermissionDao.findAll(); for(SysPermission permission : permissions) { array = new ArrayList<>(); cfg = new SecurityConfig(permission.getName()); //此處只添加了用戶的名字,其實還能夠添加更多權限的信息,例如請求方法到ConfigAttribute的集合中去。此處添加的信息將會做爲MyAccessDecisionManager類的decide的第三個參數。 array.add(cfg); //用權限的getUrl() 做爲map的key,用ConfigAttribute的集合做爲 value, map.put(permission.getUrl(), array); } } //此方法是爲了斷定用戶請求的url 是否在權限表中,若是在權限表中,則返回給 decide 方法,用來斷定用戶是否有此權限。若是不在權限表中則放行。 @Override public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException { if(map ==null) loadResourceDefine(); //object 中包含用戶請求的request 信息 HttpServletRequest request = ((FilterInvocation) object).getHttpRequest(); AntPathRequestMatcher matcher; String resUrl; for(Iterator<String> iter = map.keySet().iterator(); iter.hasNext(); ) { resUrl = iter.next(); matcher = new AntPathRequestMatcher(resUrl); if(matcher.matches(request)) { return map.get(resUrl); } } return null; } @Override public Collection<ConfigAttribute> getAllConfigAttributes() { return null; } @Override public boolean supports(Class<?> clazz) { return true; } }
6、根據權限設置鏈接
對於權限管理,咱們可能但願,在一個用戶訪問的界面中,不是等到用戶點擊了超連接以後,纔來判斷用戶有沒有這個權限,而是按照用戶擁有的權限來顯示超連接。這樣的設計對於用戶體驗來講,會更友好。
6.一、方法1:使用sec標籤(thymeleaf)
在html標籤中引入的Spring Security的標籤:
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4"
sec:authentication="name":取當前登陸用戶的用戶名
<title sec:authentication="name"></title>
sec:authorize="hasRole('ROLE_ADMIN'):表示當前用戶是否擁有角色ROLE_ADMIN
<li sec:authorize="hasRole('ROLE_ADMIN')"><a th:href="@{/admin}"> admin </a></li>
sec:authorize="hasAuthority('admin')":表示當前用戶是否擁有權限admin
<li sec:authorize="hasAuthority('admin')"><a th:href="@{/admin}"> admin </a></li>
6.二、方法二:代碼
在控制層用代碼獲取是否有權限,而後將標識放入內容中,頁面獲取處理
7、其它代碼
7.一、controller
IndexController.java
package com.example.demo.controller; import com.example.demo.domain.Msg; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; /** * 描述 * * @Author: 我愛大金子 * @Description: 描述 * @Date: Create in 15:25 2017/7/5 */ @Controller public class IndexController { /**系統首頁*/ @RequestMapping("/") public String index(Model model){ Msg msg = new Msg("測試標題","測試內容","歡迎來到HOME頁面,您擁有index權限"); model.addAttribute("msg", msg); return "home"; } /**系統首頁2*/ @RequestMapping("/index2") public String index2(Model model){ Msg msg = new Msg("測試標題2","測試內容2","歡迎來到HOME頁面,您擁有home權限"); model.addAttribute("msg", msg); return "home"; } @RequestMapping("/admin") @ResponseBody public String hello(){ return "hello admin"; } @RequestMapping("/yk") @ResponseBody public String hello2(){ return "hello yk"; } }
7.二、dao
SysUserDao.java
package com.example.demo.dao; import com.example.demo.pojo.SysUser; import org.apache.ibatis.annotations.Mapper; /** * 系統用戶dao * * @Author: 我愛大金子 * @Description: 系統用戶dao * @Date: Create in 16:15 2017/7/5 */ @Mapper public interface SysUserDao { public SysUser findByUserName(String username); }
SysPermissionDao.java
package com.example.demo.dao; import com.example.demo.pojo.SysPermission; import org.apache.ibatis.annotations.Mapper; import java.util.List; /** * 系統權限dao * * @Author: 我愛大金子 * @Description: 描述 * @Date: Create in 17:05 2017/7/5 */ @Mapper public interface SysPermissionDao { List<SysPermission> findAll(); List<SysPermission> findByAdminUserId(Long userId); }
7.三、domain
Msg.java
package com.example.demo.domain; /** * 描述 * * @Author: 我愛大金子 * @Description: 描述 * @Date: Create in 16:14 2017/7/5 */ public class Msg { private String title; private String content; private String etraInfo; public Msg(String title, String content, String etraInfo) { super(); this.title = title; this.content = content; this.etraInfo = etraInfo; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getEtraInfo() { return etraInfo; } public void setEtraInfo(String etraInfo) { this.etraInfo = etraInfo; } }
7.四、pojo
SysUser.java
package com.example.demo.pojo; import java.util.List; /** * 系統用戶 * * @Author: 我愛大金子 * @Description: 系統用戶 * @Date: Create in 16:12 2017/7/5 */ public class SysUser { private Long id; private String username; private String password; private List<SysRole> roles; public Long getId() { return id; } public void setId(Long 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<SysRole> getRoles() { return roles; } public void setRoles(List<SysRole> roles) { this.roles = roles; } }
SysRole.java
package com.example.demo.pojo; /** * 系統角色 * * @Author: 我愛大金子 * @Description: 系統角色 * @Date: Create in 16:13 2017/7/5 */ public class SysRole { private Long id; private String name; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
SysPermission.java
package com.example.demo.pojo; /** * 系統權限 * * @Author: 我愛大金子 * @Description: 系統權限 * @Date: Create in 17:04 2017/7/5 */ public class SysPermission { private Long id; //權限名稱 private String name; //權限描述 private String descritpion; //受權連接 private String url; //父節點id private int pid; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescritpion() { return descritpion; } public void setDescritpion(String descritpion) { this.descritpion = descritpion; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public int getPid() { return pid; } public void setPid(int pid) { this.pid = pid; } }
7.五、mapperXX.xml
SysUserDao.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace="com.example.demo.dao.SysUserDao" > <resultMap id="userMap" type="SysUser"> <id property="id" column="ID"/> <result property="username" column="username"/> <result property="password" column="PASSWORD"/> <collection property="roles" ofType="SysRole"> <result column="name" property="name"/> </collection> </resultMap> <select id="findByUserName" parameterType="String" resultMap="userMap"> select u.* ,r.name from sys_user u LEFT JOIN sys_user_role sru on u.id= sru.sys_user_id LEFT JOIN sys_role r on sru.sys_role_id=r.id where username= #{username} </select> </mapper>
SysPermissionDao.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace="com.example.demo.dao.SysPermissionDao" > <select id="findAll" resultType="SysPermission"> SELECT * from sys_permission ; </select> <select id="findByAdminUserId" parameterType="java.lang.Long" resultType="SysPermission"> SELECT p.* FROM sys_user u LEFT JOIN sys_user_role sru ON u.id= sru.sys_user_id LEFT JOIN sys_role r ON sru.sys_role_id=r.id LEFT JOIN sys_role_permission spr ON spr.sys_role_id=r.id LEFT JOIN Sys_permission p ON p.id =spr.sys_permission_id WHERE u.id=#{userId} </select> </mapper>
7.六、html
login.html
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> <meta content="text/html;charset=UTF-8"/> <title>登陸頁面</title> <link rel="stylesheet" th:href="@{css/bootstrap.min.css}"/> <style type="text/css"> body { padding-top: 50px; } .starter-template { padding: 40px 15px; text-align: center; } </style> </head> <body> <nav class="navbar navbar-inverse navbar-fixed-top"> <div class="container"> <div class="navbar-header"> <a class="navbar-brand" href="#">Spring Security演示</a> </div> <div id="navbar" class="collapse navbar-collapse"> <ul class="nav navbar-nav"> <li><a th:href="@{/}"> 首頁 </a></li> </ul> </div><!--/.nav-collapse --> </div> </nav> <div class="container"> <div class="starter-template"> <p th:if="${param.logout}" class="bg-warning">已成功註銷</p><!-- 1 --> <p th:if="${param.illegal}" class="bg-warning">無權訪問,請切換帳號登陸</p><!-- 1 --> <p th:if="${param.error}" class="bg-danger">用戶名或密碼錯誤</p> <!-- 2 --> <h2>使用帳號密碼登陸</h2> <form name="form" th:action="@{/login}" action="/login" method="POST"> <!-- 3 --> <div class="form-group"> <label for="username">帳號</label> <input type="text" class="form-control" name="username" value="" placeholder="帳號" /> </div> <div class="form-group"> <label for="password">密碼</label> <input type="password" class="form-control" name="password" placeholder="密碼" /> </div> <input type="submit" id="login" value="Login" class="btn btn-primary" /> </form> </div> </div> </body> </html>
home.html
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4"> <head> <meta content="text/html;charset=UTF-8"/> <title sec:authentication="name"></title> <link rel="stylesheet" th:href="@{css/bootstrap.min.css}" /> <style type="text/css"> body { padding-top: 50px; } .starter-template { padding: 40px 15px; text-align: center; } </style> </head> <body> <nav class="navbar navbar-inverse navbar-fixed-top"> <div class="container"> <div class="navbar-header"> <a class="navbar-brand" href="#">Spring Security演示</a> </div> <div id="navbar" class="collapse navbar-collapse"> <ul class="nav navbar-nav"> <li><a th:href="@{/}"> 首頁 </a></li> <li sec:authorize="hasAuthority('admin')"><a th:href="@{/admin}"> admin </a></li> </ul> </div><!--/.nav-collapse --> </div> </nav> <div class="container"> <div class="starter-template"> <h1 th:text="${msg.title}"></h1> <p class="bg-primary" th:text="${msg.content}"></p> <div> <p class="bg-info" th:text="${msg.etraInfo}"></p> </div> <form th:action="@{/logout}" method="post"> <input type="submit" class="btn btn-primary" value="註銷"/> </form> </div> </div> </body> </html>