Spring整合Shiro及簡單實用
阿新 • • 發佈:2018-12-01
匯入依賴
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.6.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.0.6.RELEASE</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.3.2</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-web</artifactId> <version>1.3.2</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.3.2</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.9</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.0.6.RELEASE</version> </dependency>
Spring-Context配置相應Bean
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager"/> <property name="loginUrl" value="login.html"/> <property name="unauthorizedUrl" value="403.html"/> <property name="filterChainDefinitions"> <value> /login.html = anon <!--anon的代表是不要認證的--> /subLogin = anon /* = authc <!--anon的代表是要認證的,一般放最後--> </value> </property> </bean> <!--建立SecurityManager--> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="realm" /> </bean> <bean id="realm" class="com.ay.shiro.realm.CustomRealm"> <!-- <property name="credentialsMatcher" ref="credentialsMatcher"/> --> </bean> <!--<bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher"> <property name="hashAlgorithmName" value="md5" /> <property name="hashIterations" value="1" /> </bean>-->
密碼如果使用MD5加密需要credentialsMatcher
自定義Realm
一般 user,role,permission是存在資料庫的3+2表,自定義Realm通過持久層讀取相關需要驗證的資訊。
public class CustomRealm extends AuthorizingRealm { { super.setName("customRealm"); } @Resource private UserDao userDao; @Override //授權 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { String username = (String) principalCollection.getPrimaryPrincipal(); //模擬獲取roles permission Set<String> roles = getRolesByUsername(username); Set<String> permission = getPermissionByUsername(username); SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); simpleAuthorizationInfo.setRoles(roles); simpleAuthorizationInfo.setStringPermissions(permission); return simpleAuthorizationInfo; } private Set<String> getPermissionByUsername(String username) { List<String> permission = userDao.getPermissionByUsername(username); if(permission == null){ return null; } Set<String> set = new HashSet<>(permission); return set; } private Set<String> getRolesByUsername(String username) { List<String> roles = userDao.getRolesByUsername(username); if(roles == null){ return null; } Set<String> set = new HashSet<>(roles); return set; } @Override //認證 主體提交認證後的處理 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { String username = (String) authenticationToken.getPrincipal(); //模擬從資料庫獲取密碼 String password = getPasswordByUsername(username); if(password == null){ return null; } SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo( username,password,"customRealm"); //對原密碼要進行加鹽,資料庫存的也是要進行加鹽加密的密碼 authenticationInfo.setCredentialsSalt(ByteSource.Util.bytes(username)); return authenticationInfo; } private String getPasswordByUsername(String username) { User user = userDao.getUserByUsername(username); if(user != null){ return user.getPassword(); } return null; } public static void main(String[] args){ Md5Hash md5Hash = new Md5Hash("123456","Ay"); System.out.println(md5Hash.toString()); } }
控制層
得到主體,生成token,進行認證和授權。
@RequestMapping(value = "/subLogin",method = RequestMethod.POST,
produces = "application/json;charset=utf-8")
@ResponseBody
public String subLogin(User user){
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(),user.getPassword());
try {
subject.login(token);
// subject.checkRole("admin");
// subject.checkPermission("user:select");
}catch (Exception e){
return e.getMessage();
}
return "登入成功";
}
通過註釋進行授權
<!--shiro註釋-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
bean配置
<!--開啟shiro註釋-->
<aop:config proxy-target-class="true"/>
<bean class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager" />
</bean>
示例方法
已認證的使用者需要admin才能訪問
@RequiresRoles("admin")
@RequestMapping(value = "/testRole",method = RequestMethod.GET)
@ResponseBody
public String testRole(){
return "testRole success";
}