配色: 字号:
Shrio登陆验证实例详细解读
2016-10-13 | 阅:  转:  |  分享 
  
Shrio登陆验证实例详细解读

下面来简单说下过程吧!

准备工作:

先建表:

[sql]viewplaincopy

droptableifexistsuser;

CREATETABLE`user`(

`id`int(11)primarykeyauto_increment,

`name`varchar(20)NOTNULL,

`age`int(11)DEFAULTNULL,

`birthday`dateDEFAULTNULL,

`password`varchar(20)NOTNULL

)ENGINE=InnoDBDEFAULTCHARSET=utf8;



insertintouservalues(1,''lin'',12,''2013-12-01'',''123456'');

insertintouservalues(2,''apple'',34,''1999-12-01'',''123456'');

insertintouservalues(3,''evankaka'',23,''2017-12-01'',''123456'');



建好后,新建一个Maven的webApp的工程,记得把结构设置成上面的那样!

下面来看看一些代码和配置

1、POM文件

注意不要少导包了,如果项目出现红叉,一般都是JDK版本的设置问题,自己百度一下就可以解决

[html]viewplaincopy


xsi:schemaLocation="http://maven.apache.org/POM/4.0.0http://maven.apache.org/maven-v4_0_0.xsd">

4.0.0

com.lin

ShiroLearn1

war

0.0.1-SNAPSHOT

ShiroLearn1MavenWebapp

http://maven.apache.org





3.2.8.RELEASE



1.6.6

1.2.12



4.10



3.2.1









org.springframework

spring-core

${spring.version}





org.springframework

spring-webmvc

${spring.version}





org.springframework

spring-context

${spring.version}





org.springframework

spring-context-support

${spring.version}





org.springframework

spring-aop

${spring.version}





org.springframework

spring-aspects

${spring.version}





org.springframework

spring-tx

${spring.version}





org.springframework

spring-jdbc

${spring.version}





org.springframework

spring-web

${spring.version}









junit

junit

${junit.version}

test











log4j

log4j

${log4j.version}





org.slf4j

slf4j-api

${slf4j.version}





org.slf4j

slf4j-log4j12

${slf4j.version}











org.springframework

spring-test

${spring.version}

test









org.mybatis

mybatis

${mybatis.version}









org.mybatis

mybatis-spring

1.2.0









mysql

mysql-connector-java

5.1.29









javax.servlet

servlet-api

3.0-alpha-1









org.apache.shiro

shiro-core

1.2.1





org.apache.shiro

shiro-web

1.2.1





org.apache.shiro

shiro-ehcache

1.2.1





org.apache.shiro

shiro-spring

1.2.1











ShiroLearn1







maven-war-plugin



2.4









org.apache.maven.plugins

maven-compiler-plugin

2.3.2



1.6

1.6













2、自定义Shiro拦截器

这里这个拦截器完成了用户名和密码的验证,验证成功后又给用赋角色和权限(注意,这里赋角色和权限我直接写进去了,没有使用数据库,一般都是要通过service层找到用户名后,再去数据库查该用户对应的角色以及权限,然后再加入到shiro中去)



代码如下:

[java]viewplaincopy

packagecom.lin.realm;



importjava.util.HashSet;

importjava.util.Set;



importorg.apache.shiro.authc.AuthenticationException;

importorg.apache.shiro.authc.AuthenticationInfo;

importorg.apache.shiro.authc.AuthenticationToken;

importorg.apache.shiro.authc.SimpleAuthenticationInfo;

importorg.apache.shiro.authc.UsernamePasswordToken;

importorg.apache.shiro.authz.AuthorizationInfo;

importorg.apache.shiro.authz.SimpleAuthorizationInfo;

importorg.apache.shiro.cache.Cache;

importorg.apache.shiro.realm.AuthorizingRealm;

importorg.apache.shiro.subject.PrincipalCollection;

importorg.apache.shiro.subject.SimplePrincipalCollection;

importorg.slf4j.Logger;

importorg.slf4j.LoggerFactory;

importorg.springframework.beans.factory.annotation.Autowired;



importcom.lin.domain.User;

importcom.lin.service.UserService;

importcom.lin.utils.CipherUtil;



publicclassShiroDbRealmextendsAuthorizingRealm{

privatestaticLoggerlogger=LoggerFactory.getLogger(ShiroDbRealm.class);

privatestaticfinalStringALGORITHM="MD5";



@Autowired

privateUserServiceuserService;



publicShiroDbRealm(){

super();

}



/

验证登陆

/

@Override

protectedAuthenticationInfodoGetAuthenticationInfo(

AuthenticationTokenauthcToken)throwsAuthenticationException{

UsernamePasswordTokentoken=(UsernamePasswordToken)authcToken;

System.out.println(token.getUsername());

Useruser=userService.findUserByLoginName(token.getUsername());

System.out.println(user);

CipherUtilcipher=newCipherUtil();//MD5加密

if(user!=null){

returnnewSimpleAuthenticationInfo(user.getName(),cipher.generatePassword(user.getPassword()),getName());

}else{

thrownewAuthenticationException();

}

}



/

登陆成功之后,进行角色和权限验证

/

@Override

protectedAuthorizationInfodoGetAuthorizationInfo(PrincipalCollectionprincipals){

/这里应该根据userName使用role和permission的serive层来做判断,并将对应的权限加进来,下面简化了这一步/

SetroleNames=newHashSet();

Setpermissions=newHashSet();

roleNames.add("admin");//添加角色。对应到index.jsp

roleNames.add("administrator");

permissions.add("create");//添加权限,对应到index.jsp

permissions.add("login.do?main");

permissions.add("login.do?logout");

SimpleAuthorizationInfoinfo=newSimpleAuthorizationInfo(roleNames);

info.setStringPermissions(permissions);

returninfo;

}





/

清除所有用户授权信息缓存.

/

publicvoidclearCachedAuthorizationInfo(Stringprincipal){

SimplePrincipalCollectionprincipals=newSimplePrincipalCollection(principal,getName());

clearCachedAuthorizationInfo(principals);

}





/

清除所有用户授权信息缓存.

/

publicvoidclearAllCachedAuthorizationInfo(){

Cachecache=getAuthorizationCache();

if(cache!=null){

for(Objectkey:cache.keys()){

cache.remove(key);

}

}

}



//@PostConstruct

//publicvoidinitCredentialsMatcher(){//MD5鍔犲瘑

//HashedCredentialsMatchermatcher=newHashedCredentialsMatcher(ALGORITHM);

//setCredentialsMatcher(matcher);

//}

}

3、shiro的配置文件:spring-shiro.xml

内容如下:

[html]viewplaincopy




xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"

default-lazy-init="true">



ShiroConfiguration









































/index.html=authc

/checkLogin.do=anon

/login.do=anon

/logout.html=anon

/=authc
























depends-on="lifecycleBeanPostProcessor">

















这里简要说明下:

(1)

securityManager:这个属性是必须的。



loginUrl:没有登录的用户请求需要登录的页面时自动跳转到登录页面,不是必须的属性,不输入地址的话会自动寻找项目web项目的根目录下的”/login.jsp”页面。



successUrl:登录成功默认跳转页面,不配置则跳转至”/”。如果登陆前点击的一个需要登录的页面,则在登录自动跳转到那个需要登录的页面。不跳转到此。



unauthorizedUrl:没有权限默认跳转的页面。

(2)

anon:例子/admins/=anon没有参数,表示可以匿名使用。



authc:例如/admins/user/=authc表示需要认证(登录)才能使用,没有参数



roles:例子/admins/user/=roles[admin],参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,当有多个参数时,例如admins/user/=roles["admin,guest"],每个参数通过才算通过,相当于hasAllRoles()方法。



perms:例子/admins/user/=perms[user:add:],参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,例如/admins/user/=perms["user:add:,user:modify:"],当有多个参数时必须每个参数都通过才通过,想当于isPermitedAll()方法。



rest:例子/admins/user/=rest[user],根据请求的方法,相当于/admins/user/=perms[user:method],其中method为post,get,delete等。



port:例子/admins/user/=port[8081],当请求的url的端口不是8081是跳转到schemal://serverName:8081?queryString,其中schmal是协议http或https等,serverName是你访问的host,8081是url配置里port的端口,queryString



是你访问的url里的?后面的参数。



authcBasic:例如/admins/user/=authcBasic没有参数表示httpBasic认证



ssl:例子/admins/user/=ssl没有参数,表示安全的url请求,协议为https



user:例如/admins/user/=user没有参数表示必须存在用户,当登入操作时不做检查



注:anon,authcBasic,auchc,user是认证过滤器,



perms,roles,ssl,rest,port是授权过滤器

4、web.xml配置解读shiro的配置文件(上面的)

[html]viewplaincopy




xmlns="http://java.sun.com/xml/ns/javaee"xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"

xsi:schemaLocation="http://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"

id="WebApp_ID"version="2.5">

ArchetypeCreatedWebApplication





/login.do









contextConfigLocation

classpath:application.xml,classpath:shiro/spring-shiro.xml







webAppRootKey

springmvc.root











SpringEncodingFilter

org.springframework.web.filter.CharacterEncodingFilter



encoding

UTF-8





forceEncoding

true







SpringEncodingFilter

/







shiroFilter

org.springframework.web.filter.DelegatingFilterProxy



targetFilterLifecycle

true







shiroFilter

/











log4jConfigLocation

classpath:log4j.properties







log4jRefreshInterval

6000





org.springframework.web.util.Log4jConfigListener







org.springframework.web.context.ContextLoaderListener









org.springframework.web.util.IntrospectorCleanupListener









dispatcherServlet

org.springframework.web.servlet.DispatcherServlet



contextConfigLocation



classpath:springmvc/spring-mvc.xml



1







dispatcherServlet

/









15





404

/WEB-INF/views/error/404.jsp





401

/WEB-INF/views/error/401.jsp







这里不仅配置了SpringMVC还要配置Shiro!

5、登陆页面login.jsp

以下是默认登陆的界面



[html]viewplaincopy

<%@pagelanguage="java"contentType="text/html;charset=UTF-8"pageEncoding="UTF-8"%>

<%

Stringurl=request.getRequestURL().toString();

url=url.substring(0,url.indexOf(''/'',url.indexOf("//")+2));

Stringcontext=request.getContextPath();

url+=context;

application.setAttribute("ctx",url);

%>









Inserttitlehere







username:


password:












6、验证成功页面index.jsp

如果用户名和密码正确后,跳转到的页面

[html]viewplaincopy

<%@pagelanguage="java"contentType="text/html;charset=UTF-8"

pageEncoding="UTF-8"%>

<%@taglibprefix="shiro"uri="http://shiro.apache.org/tags"%>

<%

Stringurl=request.getRequestURL().toString();

url=url.substring(0,url.indexOf(''/'',url.indexOf("//")+2));

Stringcontext=request.getContextPath();

url+=context;

application.setAttribute("ctx",url);

%>









Shiro登陆实例





Shiro登陆实例

退出

一、验证当前用户是否为"访客",即未认证(包含未记住)的用户





Hithere!PleaseLoginorSignuptoday!



二、认证通过或已记住的用户





WelcomebackJohn!NotJohn?Clickheretologin.



三、已认证通过的用户。不包含已记住的用户,这是与user标签的区别所在。





Updateyourcontactinformation
.



四、未认证通过用户,与authenticated标签相对应。与guest标签的区别是,该标签包含已记住用户。





Pleaselogininordertoupdateyourcreditcardinformation.



五、输出当前用户信息,通常为登录帐号信息



Hello,,howareyoutoday?

六、验证当前用户是否属于该角色





Administerthesystem



七、与hasRole标签逻辑相反,当用户不属于该角色时验证通过





Sorry,youarenotallowedtoadministerthesystem.



八、验证当前用户是否属于以下任意一个角色。





Youareeitheradeveloper,manager,oradministrator.



九、验证当前用户权限。





当前用户拥有增加的权限!!!!!!!!!!!!!









当前用户拥有删除的权限!!!!!!!!!!!!!











其它页面就不说了,具体看工程吧!

7、controller层来看看

这里/{id}/showUser主要是来验证是否连接成功(现在无法测试了),当然在工程里你也可以到src/test/java里的包com.lin.service下的UserServiceTest.java,那里我也写了一个单元测试的类。

[java]viewplaincopy

packagecom.lin.controller;



importjavax.servlet.http.HttpServletRequest;

importjavax.servlet.http.HttpServletResponse;



importorg.apache.shiro.SecurityUtils;

importorg.apache.shiro.authc.UsernamePasswordToken;

importorg.apache.shiro.subject.Subject;

importorg.slf4j.Logger;

importorg.slf4j.LoggerFactory;

importorg.springframework.beans.factory.annotation.Autowired;

importorg.springframework.stereotype.Controller;

importorg.springframework.ui.Model;

importorg.springframework.web.bind.annotation.PathVariable;

importorg.springframework.web.bind.annotation.RequestMapping;

importorg.springframework.web.bind.annotation.RequestMethod;

importorg.springframework.web.bind.annotation.ResponseBody;



importcom.lin.domain.User;

importcom.lin.realm.ShiroDbRealm;

importcom.lin.service.UserService;

importcom.lin.utils.CipherUtil;



@Controller

publicclassUserControler{

privatestaticLoggerlogger=LoggerFactory.getLogger(ShiroDbRealm.class);

@Autowired

privateUserServiceuserService;



/

验证springmvc与batis连接成功

@paramid

@paramrequest

@return

/

@RequestMapping("/{id}/showUser")

publicStringshowUser(@PathVariableintid,HttpServletRequestrequest){

Useruser=userService.getUserById(id);

System.out.println(user.getName());

request.setAttribute("user",user);

return"showUser";

}



/

初始登陆界面

@paramrequest

@return

/

@RequestMapping("/login.do")

publicStringtologin(HttpServletRequestrequest,HttpServletResponseresponse,Modelmodel){

logger.debug("来自IP["+request.getRemoteHost()+"]的访问");

return"login";

}



/

验证用户名和密码

@paramrequest

@return

/

@RequestMapping("/checkLogin.do")

publicStringlogin(HttpServletRequestrequest){

Stringresult="login.do";

//取得用户名

Stringusername=request.getParameter("username");

//取得密码,并用MD5加密

Stringpassword=CipherUtil.generatePassword(request.getParameter("password"));

//Stringpassword=request.getParameterwww.baiyuewang.net("password");

UsernamePasswordTokentoken=newUsernamePasswordToken(username,password);



SubjectcurrentUser=SecurityUtils.getSubject();

try{

System.out.println("----------------------------");

if(!currentUser.isAuthenticated()){//使用shiro来验证

token.setRememberMe(true);

currentUser.login(token);//验证角色和权限

}

System.out.println("result:"+result);

result="index";//验证成功

}catch(Exceptione){

logger.error(e.getMessage());

result="login。do";//验证失败

}

returnresult;

}



/

退出

@return

/

@RequestMapping(value="/logout")

@ResponseBody

publicStringlogout(){



SubjectcurrentUser=SecurityUtils.getSubject();

Stringresult="logout";

currentUser.logout();

returnresult;

}



}

献花(0)
+1
(本文系thedust79首藏)