1. 程式人生 > >Spring Security原始碼分析十六:Spring Security專案實戰

Spring Security原始碼分析十六:Spring Security專案實戰

Spring Security是一個能夠為基於Spring的企業應用系統提供宣告式的安全訪問控制解決方案的安全框架。它提供了一組可以在Spring應用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反轉Inversion of Control ,DI:Dependency Injection 依賴注入)和AOP(面向切面程式設計)功能,為應用系統提供宣告式的安全訪問控制功能,減少了為企業系統安全控制編寫大量重複程式碼的工作。

前言

技術棧

  • Spring Boot
  • Spring Security
  • Spring Social(需配置host127.0.0.1 www.merryyou.cn
  • Spring Data JPA
  • Freemarker
  • Mysql
  • Redis
  • 前端miniui(非開源)

效果圖

https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/logback/logback_01.png
https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/logback/logback_02.png
https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/logback/logback_03.png
https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/logback/logback_04.png
https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/logback/logback_05.png
https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/logback/logback_06.png
https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/logback/logback_07.png
https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/logback/logback_08.png
https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/logback/logback_09.png
https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/logback/logback_10.png

部分程式碼

$.ajax({
            url: "${re.contextPath}/connect",
            type: "get",
            async: true,
            dataType: "json",
            success: function (data) {
                if (data.code === 0
) { if (data.data.qq) { //解綁 $("#bindingQq").attr("title", "解綁") $(".fa-qq").addClass("social_title"); } else { //繫結 $("#bindingQq").attr("title"
, "繫結") $(".fa-qq").removeClass("social_title"); } if (data.data.weixin) { //解綁 $("#bindingWeixin").attr("title", "解綁") $(".fa-weixin").addClass("social_title"); } else { //繫結 $("#bindingWeixin").attr("title", "繫結") $(".fa-weixin").removeClass("social_title"); } if (data.data.weibo) { //解綁 $("#bindingWeibo").attr("title", "解綁") $(".fa-weibo").addClass("social_title"); } else { //繫結 $("#bindingWeibo").attr("title", "繫結") $(".fa-weibo").removeClass("social_title"); } } }, error: function (XMLHttpRequest, textStatus, errorThrown) { alert(XMLHttpRequest.status); alert(XMLHttpRequest.readyState); alert(textStatus); // paser error; } });
$.ajax({
                url: "${re.contextPath}/role/" + data.id,
                cache: false,
                success: function (text) {
                    var o = mini.decode(text);
                    //設定數的選中狀態
                    console.log(o.menuIds);
                    var nodes = tree.getAllChildNodes(tree.getRootNode());
                    for(var i=0;i<nodes.length;i++){
                        if(o.menuIds.indexOf(nodes[i]['id'])>=0){
                            tree.checkNode(nodes[i]);
                        }else{
                            tree.uncheckNode(nodes[i]);
                        }
                    }
                    form.setData(o);
                    form.setChanged(false);
                }
            });
    @Override
    public List<MenuDto> getMenusList() {
        return repository.findAll().stream()
                .map(e ->new MenuDto(e.getId(), e.getPId(), e.getName(), e.getUrl()))
                .collect(Collectors.toList());
    }

    @Override
    public Set<String> getUrlByname(String username) {
        Set<SysMenu> mesnus = new HashSet<>();
        userRepository.findByUsername(username)
                .getRoles()
                .forEach(e->mesnus.addAll(e.getMenus()));
        return mesnus.stream().map(e->e.getUrl()).collect(Collectors.toSet());
    }
protected void configure(HttpSecurity http) throws Exception {
//        http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class)
        http.headers().frameOptions().disable().and()
                .formLogin()//使用表單登入,不再使用預設httpBasic方式
                .loginPage(SecurityConstants.DEFAULT_UNAUTHENTICATION_URL)//如果請求的URL需要認證則跳轉的URL
                .loginProcessingUrl(SecurityConstants.DEFAULT_SIGN_IN_PROCESSING_URL_FORM)//處理表單中自定義的登入URL
                .successHandler(merryyouLoginSuccessHandler)//登入成功處理器,返回JSON
                .failureHandler(merryyouAuthenticationfailureHandler)//登入失敗處理器
                .and()
                .apply(validateCodeSecurityConfig)//驗證碼攔截
                .and()
                .apply(smsCodeAuthenticationSecurityConfig)
                .and()
                .apply(merryyouSpringSocialConfigurer)//社交登入
                .and()
                .rememberMe()
                .tokenRepository(persistentTokenRepository())
                .tokenValiditySeconds(securityProperties.getRememberMeSeconds())
                .userDetailsService(userDetailsService)
                .and()
                .sessionManagement()
//                .invalidSessionStrategy(invalidSessionStrategy)
                .invalidSessionUrl("/session/invalid")
                .maximumSessions(securityProperties.getSession().getMaximumSessions())//最大session併發數量1
                .maxSessionsPreventsLogin(securityProperties.getSession().isMaxSessionsPreventsLogin())//之後的登入踢掉之前的登入
                .expiredSessionStrategy(sessionInformationExpiredStrategy)
                .and()
                .and()
                .logout()
                .logoutUrl("/signOut")//預設退出地址/logout
                .logoutSuccessUrl("/")//退出之後跳轉到註冊頁面
                .deleteCookies("JSESSIONID")
                .and()
                .authorizeRequests().antMatchers(SecurityConstants.DEFAULT_UNAUTHENTICATION_URL,
                SecurityConstants.DEFAULT_SIGN_IN_PROCESSING_URL_FORM,
                SecurityConstants.DEFAULT_REGISTER_URL,
                SecurityConstants.DEFAULT_SIGN_IN_PROCESSING_URL_MOBILE,
                SecurityConstants.DEFAULT_SIGN_IN_URL_MOBILE_PAGE,
                "/register",
                "/socialRegister",//社交賬號註冊和繫結頁面
                "/user/register",//處理社交註冊請求
                "/social/info",//獲取當前社交使用者資訊
                "/session/invalid",
                "/**/*.js",
                "/**/*.css",
                "/**/*.jpg",
                "/**/*.png",
                "/**/*.woff2",
                "/code/*")
                .permitAll()//以上的請求都不需要認證
                //.antMatchers("/").access("hasRole('USER')")
                .and()
                .csrf().disable()//關閉csrd攔截
        ;
        //安全模組單獨配置
        authorizeConfigProvider.config(http.authorizeRequests());
    }
@PreAuthorize("hasAnyAuthority('user:select','user:update')")
    @PostMapping(value = "/user/saveUser")
    @ResponseBody
    public Result saveUser(@RequestParam String data) {
        log.info(data);
        return sysUserService.save(data);
    }
<td style="width:100%;">
                     <@sec.authorize access="hasAuthority('role:add')">
                    <a class="mini-button" iconCls="icon-add" onclick="add()">增加</a>
                     </@sec.authorize>
                     <@sec.authorize access="hasAuthority('role:update')">
                    <a class="mini-button" iconCls="icon-add" onclick="edit()">編輯</a>
                     <@sec.authorize access="hasAuthority('role:del')">
                      </@sec.authorize>
                    <a class="mini-button" iconCls="icon-remove" onclick="remove()">刪除</a>
                     </@sec.authorize>
                </td>

啟動方式

  1. 修改application.yml中資料來源資訊,執行db資料夾下面的sql檔案
  2. 修改application-dev.yml 中redis連線資訊
  3. 社交登入需配置host檔案:127.0.0.1 www.merryyou.cn 微信appid已過期

程式碼下載

推薦文章

https://raw.githubusercontent.com/longfeizheng/longfeizheng.github.io/master/images/wechat/xiaochengxu.png

������關注微信小程式java架構師歷程
上下班的路上無聊嗎?還在看小說、新聞嗎?不知道怎樣提高自己的技術嗎?來吧這裡有你需要的java架構文章,1.5w+的java工程師都在看,你還在等什麼?