老規矩開始以前的兩問:幹什麼,爲何這麼幹css
場景:html
根本問題:任何多用戶的系統都存在身份鑑權。簡單來講,不一樣用戶在同一個系統有不一樣的操做,那麼系統必然要識別用戶。前端
產生問題:身份識別以後,對於一個系統來講,就能夠進行正常使用,可是這個時候任何人均可以得到系統的信息,這就產生了受權。git
爲何使用shiro?web
shiro是一款專門用來身份識別與受權的框架spring
shiro能幹什麼?sql
進行身份識別和受權數據庫
開始:apache
1:pom.xml 引入相關包session
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-web</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-ehcache</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.2.2</version> </dependency>
2:首先是身份識別的問題,通常的咱們都是經過輸入的用戶名和密碼去數據庫進行比對
那麼對於shiro來講,咱們只須要準備前端傳的參數和數據庫的參數,shiro就會爲咱們自動比對
(1)前端數據:
<from> <input name="username"/> <input name="password"> <input type="submit"> </from>
(2) 數據庫
CREATE TABLE `fsp_user` ( `UUID` varchar(50) NOT NULL, `F_NICKNAME` varchar(100) DEFAULT NULL, `F_PASSWORD` varchar(100) DEFAULT NULL, PRIMARY KEY (`UUID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO `fsp_user` VALUES ('90feec5c-67bd-4fb2-b360-8b0387c4c009', 'admin', '87632a5ef1d47286da9c1361717a1312');
(3)登陸比對
這一步是由shiro來完成,shiro須要知道咱們的 輸入參數和數據庫的數據
在此以前shiro須要初始化
shiro的中心管理器是SecurityManager,那麼第一步就是要配置SecurityManager
@Bean public SecurityManager securityManager() { //new 一個DefaultWebSecurityManager DefaultSecurityManager defaultSecurityManager = new DefaultWebSecurityManager(); //realm 就是從數據庫取出數據比對登陸 defaultSecurityManager.setRealm(myShiroRealm()); //session管理器 defaultSecurityManager.setSessionManager(sessionManager()); //cache管理器 defaultSecurityManager.setCacheManager(cacheManager()); //咱們須要對密碼進行加密 使用md5,加密10次 HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher("md5"); hashedCredentialsMatcher.setHashIterations(10); myShiroRealm().setCredentialsMatcher(hashedCredentialsMatcher); SecurityUtils.setSecurityManager(defaultSecurityManager); return defaultSecurityManager; }
@Bean //session 管理器 public DefaultWebSessionManager sessionManager(){ DefaultWebSessionManager defaultWebSessionManager = new DefaultWebSessionManager(); SimpleCookie simpleCookie= new SimpleCookie(); simpleCookie.setName("jeesite.session.id"); defaultWebSessionManager.setSessionIdCookie(simpleCookie); defaultWebSessionManager.setSessionDAO(sessionDAO()); return defaultWebSessionManager; } //session的增刪改查操做 @Bean public MemorySessionDAO sessionDAO(){ return new MemorySessionDAO(); } //cache管理器 @Bean public CacheManager cacheManager(){ return new EhCacheManager(); }
@Bean //取出數據庫的數據 這個是咱們自定義的 public UserRealm myShiroRealm(){ return new UserRealm(); }
//咱們定義的數據源集成自AuthorizingRealm public class UserRealm extends AuthorizingRealm { private Logger logger = LoggerFactory.getLogger(AuthorizingRealm.class); //數據庫fsp_user 表對應的mybatis mapper接口 @Autowired private FspUserDao fspUserDao; //受權 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); return authorizationInfo; } //登陸 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { //1,得到前端傳值 String username = (String) authenticationToken.getPrincipal(); //去數據庫查詢 FspUser user = fspUserDao.isSelect("F_IPONE",username); if (user == null) { //沒找到賬號 throw new UnknownAccountException(); } SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user, user.getF_PASSWORD(), ""); //鹽 authenticationInfo.setCredentialsSalt(ByteSource.Util.bytes("GGZEServer")); user.setF_PASSWORD(""); //將用戶信息放入session中 SecurityUtils.getSubject().getSession().setTimeout(-5000); SecurityUtils.getSubject().getSession().setAttribute("FSPUSER", user); return authenticationInfo; } /*//加密 public static void main(String[] args){ Md5Hash md5Hash = new Md5Hash("123456","GGZEServer",10); System.out.println(md5Hash.toString()); }*/ }
(4)配置完成後,咱們須要讓全部的請求都是合法的,就必須進行登陸,記住登陸信息,每次的請求驗證其合法性
咱們使用過濾器來過濾全部請求,
首先要使shiro認識咱們自定義的過濾器
@Bean public AutoShiro shirFilter(SecurityManager securityManager, FspDataRecordDao fspDataRecordDao) { System.out.println("ShiroConfiguration.shirFilter()"); ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); // 過濾器鏈11 Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>(); //key 爲訪問地址,value爲權限。anao所有不過濾 authc爲須要登陸 loingout爲登出 filterChainDefinitionMap.put("/css/**", "anon"); filterChainDefinitionMap.put("/login", "authc"); filterChainDefinitionMap.put("/img/**", "anon"); filterChainDefinitionMap.put("/js/**", "anon"); filterChainDefinitionMap.put("/loginout", "loginout"); shiroFilterFactoryBean.setSecurityManager(securityManager); //登陸地址設置 shiroFilterFactoryBean.setLoginUrl("/vsp_8201574998956"); //成功地址設置 shiroFilterFactoryBean.setSuccessUrl("/vsp_8201574998957"); Map<String, Filter> filters = new LinkedHashMap<String, Filter>(); AuthFilter authFilter=new AuthFilter(); authFilter.setLoginUrl("/login"); authFilter.setUsernameParam("F_IPONE"); authFilter.setPasswordParam("F_PASSWORD"); authFilter.setUserClass(FspUser.class); //設置過濾器名 filters.put("authc", authFilter); //這裏能夠設置自定義的過濾器 //設置登出 LogoutFilter logoutFilter=new LogoutFilter(); filters.put("loginout",logoutFilter); shiroFilterFactoryBean.setFilters(filters); return shiroFilterFactoryBean; }
按以上配置,shiro會認知shiro的過濾器,咱們來實現它的過濾器
public class AuthFilter extends FormAuthenticationFilter { private Class<? extends FspUser> userClass; private static final String REDIRECT_URL_PARAMETER_NAME = "redirectUrl"; //建立身份認證 @Override protected org.apache.shiro.authc.AuthenticationToken createToken(ServletRequest servletRequest, ServletResponse servletResponse) { String username = getUsername(servletRequest); String password = getPassword(servletRequest); boolean rememberMe = isRememberMe(servletRequest); String host = getHost(servletRequest); return new UsernamePasswordToken(username, password, rememberMe, host); } /** * 是否容許訪問 * * @param servletRequest ServletRequest * @param servletResponse ServletResponse * @param mappedValue 映射值 * @return 是否容許訪問 */ @Override protected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object mappedValue) { Subject subject = getSubject(servletRequest, servletResponse); Object principal = subject != null ? subject.getPrincipal() : null; if (principal == null || !FspUser.class.isAssignableFrom(principal.getClass())) { return false; } HttpServletRequest request=(HttpServletRequest) servletRequest; if(request.getServletPath().indexOf("login")>=0&&request.getSession().getAttribute("FSPUSER")!=null){ HttpServletResponse response = (HttpServletResponse)servletResponse; try { response.sendRedirect("/shopc/vsp_8201574998957"); } catch (IOException e) { e.printStackTrace(); } } return super.isAccessAllowed(servletRequest, servletResponse, mappedValue); } /** * 拒絕訪問處理 * * @param servletRequest ServletRequest * @param servletResponse ServletResponse * @return 是否繼續處理 */ @Override protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; if (isLoginRequest(request, response)) { if (isLoginSubmission(request, response)) { return executeLogin(request, response); } else { return true; } } response.sendRedirect("/shopc/vsp_8201574998956"); return false; } /** * 登陸成功處理 * * @param authenticationToken 令牌 * @param subject Subject * @param servletRequest ServletRequest * @param servletResponse ServletResponse * @return 是否繼續處理 */ @Override protected boolean onLoginSuccess(org.apache.shiro.authc.AuthenticationToken authenticationToken, Subject subject, ServletRequest servletRequest, ServletResponse servletResponse) throws Exception { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; return super.onLoginSuccess(authenticationToken, subject, servletRequest, servletResponse); } /** * 登陸失敗處理 * * @param authenticationToken 令牌 * @param authenticationException 認證異常 * @param servletRequest ServletRequest * @param servletResponse ServletResponse * @return 是否繼續處理 */ @Override protected boolean onLoginFailure(org.apache.shiro.authc.AuthenticationToken authenticationToken, AuthenticationException authenticationException, ServletRequest servletRequest, ServletResponse servletResponse) { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; return super.onLoginFailure(authenticationToken, authenticationException, servletRequest, servletResponse); } public Class<? extends FspUser> getUserClass() { return userClass; } public void setUserClass(Class<? extends FspUser> userClass) { this.userClass = userClass; } public static String getRedirectUrlParameterName() { return REDIRECT_URL_PARAMETER_NAME; }
當執行建立身份認證的時候return new UsernamePasswordToken(username, password, rememberMe, host);
會進去咱們自定義的Realm 登陸成功。
已上傳碼雲:https://gitee.com/wervernice/shirotest
未完待續