springBoot(23):spring-security-基本

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") 


wKioL1le6lbRnu1KAAFucw-RHo4498.jpg


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、其它代碼

wKioL1le-47T_WyLAABw4KXMIDA929.png

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>
相關文章
相關標籤/搜索