碼雲地址:https://gitee.com/huatao1994/springSecuritycss
/* Navicat MySQL Data Transfer Source Server : localhost Source Server Version : 50529 Source Host : localhost:3306 Source Database : security Target Server Type : MYSQL Target Server Version : 50529 File Encoding : 65001 Date: 2019-12-21 14:04:04 */ SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for `authority_menu` -- ---------------------------- DROP TABLE IF EXISTS `authority_menu`; CREATE TABLE `authority_menu` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id', `url` varchar(255) DEFAULT NULL COMMENT '請求路徑', `menu_name` varchar(255) DEFAULT NULL COMMENT '菜單名稱', `parent_id` int(11) DEFAULT NULL COMMENT '父菜單id', `update_time` varchar(255) DEFAULT NULL COMMENT '更新時間', `remark` varchar(255) DEFAULT NULL COMMENT '備註', `url_pre` varchar(255) DEFAULT NULL COMMENT '路由(前端本身匹配用)', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of authority_menu -- ---------------------------- -- ---------------------------- -- Table structure for `authority_role` -- ---------------------------- DROP TABLE IF EXISTS `authority_role`; CREATE TABLE `authority_role` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id', `role_name` varchar(255) DEFAULT NULL COMMENT '角色名稱(必須以ROLE_起始命名)', `role_name_CN` varchar(255) DEFAULT NULL COMMENT '角色名稱中文', `update_time` varchar(255) DEFAULT NULL COMMENT '更新時間', `remark` varchar(255) DEFAULT NULL COMMENT '備註', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=35 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of authority_role -- ---------------------------- -- ---------------------------- -- Table structure for `authority_role_menu` -- ---------------------------- DROP TABLE IF EXISTS `authority_role_menu`; CREATE TABLE `authority_role_menu` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id', `role_id` int(11) DEFAULT NULL, `menu_id` int(11) DEFAULT NULL, `update_time` varchar(255) DEFAULT NULL COMMENT '更新時間', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of authority_role_menu -- ---------------------------- -- ---------------------------- -- Table structure for `authority_user` -- ---------------------------- DROP TABLE IF EXISTS `authority_user`; CREATE TABLE `authority_user` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id', `username` varchar(255) DEFAULT NULL COMMENT '用戶名', `password` varchar(255) DEFAULT NULL COMMENT '密碼', `email` varchar(255) DEFAULT NULL COMMENT '郵箱', `phone` varchar(255) DEFAULT NULL COMMENT '手機號', `valid_time` varchar(255) DEFAULT NULL COMMENT '有效截止時間', `update_time` varchar(255) DEFAULT NULL COMMENT '更新時間', `remark` mediumtext COMMENT '備註', `nickname` varchar(255) DEFAULT NULL COMMENT '暱稱', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=47 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of authority_user -- ---------------------------- -- ---------------------------- -- Table structure for `authority_user_role` -- ---------------------------- DROP TABLE IF EXISTS `authority_user_role`; CREATE TABLE `authority_user_role` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id', `user_id` int(11) DEFAULT NULL, `role_id` int(11) DEFAULT NULL, `update_time` varchar(255) DEFAULT NULL COMMENT '更新時間', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=74 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of authority_user_role -- ---------------------------- -- ---------------------------- -- Table structure for `persistent_logins` -- ---------------------------- DROP TABLE IF EXISTS `persistent_logins`; 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=utf8; -- ---------------------------- -- Records of persistent_logins -- ----------------------------
package cn.**.controller; import cn.**.dao.UserDao; import cn.**.service.UserService1; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @ProjectName: springbootSecurity * @Package: cn.**.security.controller * @Author: huat * @Date: 2019/12/12 14:56 * @Version: 1.0 */ @RestController public class UserController { @Autowired UserService1 userService1; //@Secured("ROLE_ADMIN")//security權限註解 //@RolesAllowed("ROLE_ADMIN") //jsr250註解 //@PreAuthorize("hasRole('ROLE_ADMIN')")//spring的註解 @RequestMapping("/login") public String login(String username,String password){ //獲取登錄的用戶名 String username1= SecurityContextHolder.getContext().getAuthentication().getName(); System.out.println(username); return "index"; } @RequestMapping("test") public String test(){ return "hello test"; } }
package cn.**.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; /** * @ProjectName: springbootSecurity * @Package: cn.**.security.controller * @Author: huat * @Date: 2019/12/16 15:16 * @Version: 1.0 */ @Controller public class IntoController { @RequestMapping("intoTest") public String intoTest(){ return "/test"; } @RequestMapping("intoIndex") public String intoIndex(){ return "index"; } @RequestMapping("intoFail") public String intoFail(){ return "fail"; } @RequestMapping("intoLogin") public String intoLogin(){ return "login"; } @RequestMapping("dologin") public String dologin(){ return "index"; } }
package cn.**.entity; import com.fasterxml.jackson.annotation.JsonIgnore; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import java.util.Collection; import java.util.List; /** * @ProjectName: springbootSecurity * @Package: cn.**.security.entity * @Author: huat * @Date: 2019/12/12 15:12 * @Version: 1.0 * 建立實體類第一種方式 */ public class AuthorityUser implements UserDetails { private int id; private String username; private String password; private List<AuthorityRole> authorityRoles; public int getId() { return id; } public void setId(int 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<AuthorityRole> getAuthorityRoles() { return authorityRoles; } public void setAuthorityRoles(List<AuthorityRole> authorityRoles) { this.authorityRoles = authorityRoles; } @Override @JsonIgnore//忽略此屬性 轉成json字符串時不進行轉換 public Collection<? extends GrantedAuthority> getAuthorities() { return authorityRoles; } @Override @JsonIgnore//忽略此屬性 轉成json字符串時不進行轉換 public boolean isAccountNonExpired() { return true; } @Override @JsonIgnore//忽略此屬性 轉成json字符串時不進行轉換 public boolean isAccountNonLocked() { return true; } @Override @JsonIgnore//忽略此屬性 轉成json字符串時不進行轉換 public boolean isCredentialsNonExpired() { return true; } @Override @JsonIgnore//忽略此屬性 轉成json字符串時不進行轉換 public boolean isEnabled() { return true; } }
package cn.**.entity; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.databind.annotation.JsonAppend; import org.springframework.security.core.GrantedAuthority; /** * @ProjectName: springbootSecurity * @Package: cn.**.security.entity * @Author: huat * @Date: 2019/12/12 16:14 * @Version: 1.0 */ public class AuthorityRole implements GrantedAuthority { private int rid; private String roleName; private String roleNameCN; public int getRid() { return rid; } public void setRid(int rid) { this.rid = rid; } public String getRoleName() { return roleName; } public void setRoleName(String roleName) { this.roleName = roleName; } public String getRoleNameCN() { return roleNameCN; } public void setRoleNameCN(String roleNameCN) { this.roleNameCN = roleNameCN; } @JsonIgnore//忽略此屬性 轉成json字符串時不進行轉換 @Override public String getAuthority() { return roleName; } }
package cn.**.entity; /** * @ProjectName: springbootSecurity * @Package: cn.*.security.entity * @Author: huat * @Date: 2019/12/16 18:45 * @Version: 1.0 */ public class AuthorityMenu { private int id; private String url; private String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
package cn.**.service; import org.springframework.security.core.userdetails.UserDetailsService; /** * @ProjectName: springbootSecurity * @Package: cn.**.security.service * @Author: huat * @Date: 2019/12/12 17:35 * @Version: 1.0 */ //UserDetailsService 是security中的類 public interface UserService extends UserDetailsService { }
package cn.**.service; import cn.**.dao.UserDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; /** * @ProjectName: springbootSecurity * @Package: cn.**.utile * @Author: huat * @Date: 2019/12/12 14:48 * @Version: 1.0 */ @Service//將這個類注入到spring容器中 public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; @Override public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { return userDao.getUser(s); } public static void main(String[] args) { BCryptPasswordEncoder passwordEncoder=new BCryptPasswordEncoder(); //passwordEncoder.encode("123456")加密方法 //執行屢次加密後的結果均不同 //執行第一次:$2a$10$RSlzzO4xAubBLZMB8jPL8eMFX17gM61JfrgINpzOiaEsBdtKBuSDe //執行第二次:$2a$10$2uQWdP9qAXGK4H0um0gtG.o1QzbGhBlbxx8YjX526jIrVBNKyziFe //執行第三次:$2a$10$8CWttAISfamloSErsqEAPemALyZvj8VWaUCBJKcm2GE1dhFR.7oYG //security加密方式是動態加鹽 System.out.println(passwordEncoder.encode("123456")); //比較明文和密文是否一致 System.out.println(passwordEncoder.matches("123456","$2a$10$lstWyJ6NlbdZ2uVr8ncsHOUKsG0VAT4FzDdy0gqy6gbaOqpp6ouDq")); } }
package cn.**.dao; import cn.**.entity.AuthorityUser; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; /** * @ProjectName: springbootSecurity * @Package: cn.**.security.dao * @Author: huat * @Date: 2019/12/12 15:04 * @Version: 1.0 */ @Mapper public interface UserDao { /** * 根據用戶名查詢角色 * @param username 用戶名 * @return */ AuthorityUser getUser(@Param("username") String username); /** * 添加用戶 * @param username 用戶名 * @param password 密碼 * @return */ int saveUser(@Param("username") String username, @Param("password") String password); }
<?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="cn.**.dao.UserDao"> <resultMap id="userRole" type="authorityUser"> <id column="id" property="id"></id> <result column="username" property="username"></result> <result column="password" property="password"></result> <collection property="authorityRoles" ofType="authorityRole"> <id column="rid" property="rid"></id> <result property="roleName" column="role_name"></result> <result property="roleNameCN" column="role_name_CN"></result> </collection> </resultMap> <select id="getUser" resultMap="userRole"> select u.*,r.id rid,r.role_name,r.role_name_CN from authority_user u left join authority_user_role ur on ur.user_id=u.id left join authority_role r on ur.role_id=r.id where username=#{username} </select> <insert id="saveUser"> insert into authority_user(username,password) values(#{username},#{password}) </insert> </mapper>
package cn.**.util; import cn.**.service.UserService; import cn.**.service.UserService1; 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.method.configuration.EnableGlobalMethodSecurity; 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; import org.springframework.security.crypto.password.PasswordEncoder; /** * @ProjectName: springbootSecurity * @Package: cn.**.security.util * @Author: huat * @Date: 2019/12/14 8:06 * @Version: 1.0 */ /** * 開啓security註解支持 * @EnableWebSecurity * (securedEnabled=true) 開啓@Secured 註解過濾權限 * (jsr250Enabled=true)開啓@RolesAllowed 註解過濾權限 * (prePostEnabled=true) 使用表達式時間方法級別的安全性 4個註解可用 * @EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled=true,jsr250Enabled=true) */ @Configuration @EnableWebSecurity //@EnableGlobalMethodSecurity(prePostEnabled = true) @EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled=true,jsr250Enabled=true) public class SpringSercurityConfig extends WebSecurityConfigurerAdapter { /* @Autowired UserService1 userService;*/ @Autowired UserService userService; @Autowired AuthenticationSuccessHandler authenticationSuccessHandler;//ajax登錄成功使用 @Autowired AuthenticationFailureHandler authenticationFailureHandler;//ajax登錄失敗使用 /** * 將security中加密方式注入到spring容器中 * @return */ @Bean public PasswordEncoder passwordEncoder(){ return new BCryptPasswordEncoder(); } /** * 將帳號密碼設置在數據庫當中 * @param auth * @throws Exception */ @Override public void configure(AuthenticationManagerBuilder auth) throws Exception { auth //將UserDetailsService放到容器中 .userDetailsService(userService) //加密方式放入 .passwordEncoder(passwordEncoder()); } @Override public void configure(HttpSecurity http) throws Exception { //釋放靜態資源,指定資源攔截規則, // 指定自定義認證頁面,指定退出認證配置,csrf(跨域僞造請求)配置 http.authorizeRequests() .antMatchers("intoLogin","login.jsp","/css/**","fail.jsp","/intoIndex","/index.jsp").permitAll()//釋放這些資源,容許匿名訪問 .antMatchers("/**").hasAnyRole("ADMIN","USER") .anyRequest().authenticated()//其餘資源須要認證 .and() .formLogin() .loginPage("/intoLogin")//登錄頁請求的接口 .loginProcessingUrl("/dologin")//登錄地址,由springSecurity提供 .successForwardUrl("/intoTest")//登錄成功 .failureForwardUrl("/intoFail")//登陸失敗 .permitAll()//指定全部資源釋放 .and() .logout()//登出 .logoutUrl("/logout")//指定登出路徑 .logoutSuccessUrl("/login.jsp")//登出成功後跳轉的url .invalidateHttpSession(true)//是否清空session .permitAll() .and() .csrf() .disable();//關閉csrf(跨域僞造請求) } /* *//** * ajax 登錄 * @param http * @throws Exception *//* @Override public void configure(HttpSecurity http) throws Exception { //釋放靜態資源,指定資源攔截規則, // 指定自定義認證頁面,指定退出認證配置,csrf(跨域僞造請求)配置 http.authorizeRequests() .antMatchers("intoLogin","login.jsp","/css/**","fail.jsp","/intoIndex","/index.jsp").permitAll()//釋放這些資源,容許匿名訪問 .antMatchers("/**").hasAnyRole("ADMIN","USER") .antMatchers("/test").hasRole("USER") .anyRequest().authenticated()//其餘資源須要認證 .and() .formLogin() .loginPage("/intoLogin")//登錄頁請求的接口 .successHandler(authenticationSuccessHandler)//登錄成功後返回的數據 .failureHandler(authenticationFailureHandler) .loginProcessingUrl("/login")//登錄地址,由springSecurity提供 .usernameParameter("name") .passwordParameter("pwd") .permitAll()//指定全部資源釋放 .and() .logout()//登出 .logoutUrl("/logout")//指定登出路徑 .logoutSuccessUrl("/login.jsp")//登出成功後跳轉的url .invalidateHttpSession(true)//是否清空session .permitAll() .and() .cors() .and() .csrf() .disable() ;//關閉csrf(跨域僞造請求) }*/ }
package cn.**.controller; import javax.servlet.http.HttpServletRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.web.servlet.error.ErrorController; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; /** * @ProjectName: springSecurity * @Package: cn.**.controller * @Author: huat * @Date: 2019/12/23 9:43 * @Version: 1.0 * * 處理異常頁面 */ @Controller public class MyException implements ErrorController { private static Logger log = LoggerFactory.getLogger(MyException.class); @RequestMapping("/error") public String handleError(HttpServletRequest request) { log.info("進入異常跳轉"); Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code"); switch (statusCode) { case 404: log.info("404異常跳轉"); return "fail"; case 403: log.info("403異常跳轉"); return "403"; case 500: log.info("500異常跳轉"); return "/error/500"; default: log.info("默認異常跳轉"); return "/error/404"; } } @Override public String getErrorPath() { return "/error"; } }
package cn.**.util; import com.alibaba.fastjson.JSON; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.authentication.AuthenticationFailureHandler; import org.springframework.stereotype.Component; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.util.HashMap; import java.util.Map; /** * @ProjectName: securityAjax * @Package: cn.**.util * @Author: huat * @Date: 2019/12/26 9:50 * @Version: 1.0 * 登錄成功返回 */ @Component public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler { @Override public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException { Map<String,Object> map=new HashMap<String,Object>(); map.put("code",500); map.put("msg","登錄失敗"); map.put("data",""); /* httpServletResponse.setContentType("application/json;charset=utf-8");*/ PrintWriter out = httpServletResponse.getWriter(); out.write(JSON.toJSONString(map)); out.flush(); out.close(); } }
package cn.**.util; import com.alibaba.fastjson.JSON; import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.stereotype.Component; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.util.HashMap; import java.util.Map; /** * @ProjectName: securityAjax * @Package: cn.**.util * @Author: huat * @Date: 2019/12/26 9:41 * @Version: 1.0 */ @Component public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler { @Override public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException { System.out.println(httpServletRequest.getParameter("name")); Map<String,Object> map=new HashMap<String,Object>(); map.put("code",200); map.put("msg","登錄成功"); map.put("data",""); /* httpServletResponse.setContentType("application/json;charset=utf-8");*/ PrintWriter out = httpServletResponse.getWriter(); out.write(JSON.toJSONString(map)); out.flush(); out.close(); } }